上一篇地址:赶紧收藏!2024 年最常见 100道 Java 基础面试题(二十六)-CSDN博客
五十三、synchronized
和Lock
有什么区别?
synchronized
和Lock
都是Java中用于实现同步的手段,它们都可以用来确保多个线程在访问共享资源时能够保持一致性和线程安全。不过,它们之间存在一些关键的区别:
synchronized
关键字:
- 内置锁:
synchronized
是由Java虚拟机内置的同步机制,其实现依靠于底层的操作系统的互斥锁。 - 使用简便:使用
synchronized
非常简单,只需要在方法声明或代码块中加入关键字即可。 - 不可中断性:当一个线程执行
synchronized
方法或代码块时,其他线程必须等待直到该线程退出同步代码块。 - 锁自动释放:当线程执行完
synchronized
代码块或因异常退出时,锁会自动释放。 - 可重入性:
synchronized
具有可重入性,即一个线程可以多次进入其已经锁定的同步代码块。
Lock
接口:
- 显示锁:
Lock
是一个接口,属于java.util.concurrent包中的类,需要通过显示调用锁对象的方法来获取和释放锁。 - 灵活性高:
Lock
提供了比synchronized
更复杂的锁定机制,例如可以尝试非阻塞地获取锁、可以超时的获取锁、可以多个条件对象的等待和通知机制。 - 中断性:在执行
Lock
的lockInterruptibly()
方法时,如果线程正在等待获取锁,它可以响应中断,这是synchronized
所不能提供的。 - 公平性:
Lock
可以提供公平性,即锁可以按照线程请求的顺序来分配,而synchronized
无法保证这一点。 - 锁绑定多个条件:
Lock
可以与Condition
对象配合使用,可以对多个条件进行等待和通知,而synchronized
关键字只能与一个条件关联。
主要区别:
- 实现方式:
synchronized
是Java的关键字,而Lock
是一个接口。 - 锁的获取:
synchronized
在获取锁失败后会自动进入阻塞状态,而Lock
则不会,它允许你控制何时进入阻塞状态。 - 响应中断:
synchronized
不允许在等待获取锁的过程中响应中断,而Lock
提供了响应中断的机制。 - 公平性:
synchronized
不支持公平性设置,而Lock
可以设置公平性。 - 条件对象:
synchronized
没有与锁直接绑定的条件对象,而Lock
提供了Condition
接口,可以实现多条件等待。
示例代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizedVsLockExample {
private final Lock lock = new ReentrantLock();
public void lockedMethod() {
lock.lock(); // 显式获取锁
try {
// 线程安全的代码
} finally {
lock.unlock(); // 显式释放锁
}
}
}
总结:
synchronized
是Java内置的同步机制,使用简单,但功能有限。Lock
提供了更复杂的同步机制,具有更高的灵活性,但使用起来相对复杂。- 在选择使用
synchronized
还是Lock
时,需要根据具体的业务场景和性能要求来决定。如果需要简单的同步,并且不需要高级的同步特性,可以使用synchronized
。如果需要更复杂的同步控制,如尝试非阻塞获取锁、响应中断、公平性设置等,应该使用Lock
。
五十四、synchronized
和ReentrantLock
区别是什么?
synchronized
和ReentrantLock
都是Java中用于实现线程同步的手段,它们都可以用来确保多个线程在访问共享资源时能够保持一致性和线程安全。不过,它们之间存在一些关键的区别:
synchronized
关键字:
- 语法糖:
synchronized
是Java的关键字,可以通过修饰方法或代码块来实现同步。 - 内置锁:
synchronized
是由JVM实现的内置锁,也称为“Monitor”锁,其底层依赖于操作系统的互斥锁。 - 使用简便:使用
synchronized
非常简单,只需加在方法或代码块上即可。 - 不可中断性:
synchronized
无法响应中断,一旦线程获取了synchronized
锁,在锁未释放之前,其他线程只能阻塞等待。 - 不可选择性:
synchronized
锁定是不可选择的,即它不能在某些情况下选择放弃获取锁。 - 公平性:
synchronized
不支持公平性设置,锁的获取是无序的。
ReentrantLock
类:
- API形式:
ReentrantLock
是java.util.concurrent.locks
包中的一个类,是一个显式的锁。 - 灵活性:
ReentrantLock
提供了比synchronized
更灵活的锁定机制,如可尝试非阻塞获取锁、可中断获取锁、可指定公平性等。 - 响应中断:在通过
lockInterruptibly()
方法获取锁时,如果线程正在等待获取锁,它可以响应中断。 - 公平性:
ReentrantLock
支持公平性设置,可以通过构造函数设置,当设置为公平性锁时,锁的获取将按照线程请求的顺序进行。 - 可重入性:
ReentrantLock
和synchronized
一样,也是可重入的。 - 条件变量:
ReentrantLock
可以与Condition
对象配合使用,支持多条件的等待和通知,而synchronized
关键字只能与一个条件关联。
主要区别:
- 实现方式:
synchronized
是通过关键字实现的,而ReentrantLock
是通过API的形式实现的。 - 锁的获取:
ReentrantLock
提供了更多的锁获取选项,如尝试获取、可中断获取等。 - 响应中断:
ReentrantLock
支持在等待获取锁的过程中响应中断,而synchronized
不支持。 - 公平性:
ReentrantLock
可以设置为公平锁或非公平锁,而synchronized
不支持公平性设置。 - 条件对象:
ReentrantLock
可以与Condition
对象配合使用,提供更丰富的条件等待和通知机制。
示例代码:
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizedVsReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
public void lockedMethod() {
lock.lock(); // 显式获取锁
try {
// 线程安全的代码
} finally {
lock.unlock(); // 显式释放锁
}
}
}
总结:
synchronized
是Java内置的同步机制,使用简单,但功能有限。ReentrantLock
提供了更复杂的同步机制,具有更高的灵活性,但使用起来相对复杂。- 在选择使用
synchronized
还是ReentrantLock
时,需要根据具体的业务场景和性能要求来决定。如果需要简单的同步,并且不需要高级的同步特性,可以使用synchronized
。如果需要更复杂的同步控制,如尝试非阻塞获取锁、响应中断、公平性设置等,应该使用ReentrantLock
。