synchronized与ReentrantLock
synchronized与ReentrantLock
synchronized与ReentrantLock的对比主要在于以下四个方面:- 可重入性:
synchronized是可重入锁,ReentrantLock也是可重入锁。 - 依赖:
synchronized依赖于JVM,而ReentrantLock依赖于API。 - 功能:
ReentrantLock相比synchronized提供了更多的功能,主要有四点:- 等待可中断
- 可实现公平锁
- 可实现选择性通知
- 支持超时
- 是否可中断:
ReentrantLock属于可中断锁,而synchronized属于不可中断锁。
- 可重入性:
1. 可重入性
- 可重入锁也叫递归锁,指的是线程可以再次获取自己的内部锁。
- JDK提供的所有现成的
Lock实现类,以及synchronized关键字都是可重入锁。 - 示例:
1
2
3
4
5
6
7
8
9
10public class SynchronizedDemo {
public synchronized void methodA() {
System.out.println("In method A");
methodB(); // 再次获取锁
}
public synchronized void methodB() {
System.out.println("In method B");
}
} - 在上述示例中,同一个线程在调用
methodA时获取了当前对象的锁,执行methodB时可以再次获取当前对象的锁,不会产生死锁问题。
2. 依赖
synchronized是Java语言内置的同步机制,依赖于JVM的实现。ReentrantLock是JDK层面实现的,也就是API层面,需要使用lock()和unlock()方法配合try/finally来使用。
3. 功能
ReentrantLock相比synchronized提供了更多的功能,主要有以下四点:- 等待可中断:
ReentrantLock中的lock.lockInterruptibly()方法允许线程在等待锁的过程中被中断。也就是当前线程在等待获取锁的过程中被其他线程使用interrupt()中断,当前线程就会抛出InterruptedException异常,可以捕捉该异常并进行处理。 - 可实现公平锁:
ReentrantLock可以选择使用公平锁还是非公平锁,而synchronized只能是非公平锁。公平锁是指线程获取锁的顺序是按照请求锁的顺序来分配的,而非公平锁则不保证顺序。ReentrantLock默认使用非公平锁。1
2
3
4// 传入一个boolean参数,true表示公平锁,false表示非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
} - 可实现选择性通知:
synchronized关键字与wait()和notify()/notifyAll()方法相结合可以实现等待/通知机制。但是synchronized只能使用一个等待队列,而ReentrantLock可以通过Condition接口和newCondition)_方法创建多个等待队列,从而实现更灵活的等待/通知机制。 - 支持超时:
ReentrantLock提供的tryLock(timeout)方法可以指定等待获取锁的最长等待时间,超过这个时间就会获取锁失败,不会一直等待。
- 等待可中断:
4. 是否可中断
ReentrantLock属于可中断锁,而synchronized属于不可中断锁。
