ReentrantLock
对比 synchronize
- 可中断
- 可以设置超时时间
- 可以设置为公平锁
- 支持多个条件变量 waitset
与 synchronize 一样,都支持可重入
java
static ReentrantLock reentrantLock = new ReentrantLock();
public static void main(String[] args) {
reentrantLock.lock();
try {
// todo something
} finally {
reentrantLock.unlock();
}
}
可重入
可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁
如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住
API
方法 | 含义 |
---|---|
lock() | 加锁 不可中断,获取不到锁会无限等待 |
unlock() | 解锁 |
lockInterruptibly() | 如果没有竞争那么此方法就会获取Lock 对象锁 如果有竞争就进入阻塞队列,可以被其他线程用interrupt打断 |
boolean tryLock() | 尝试获取锁,如果没有获取锁则直接失败 |
boolean tryLock(int timeout, TimeUnit unit) | 尝试在N时长获取锁,如果没有获取锁则直接失败 |
Condition newCondition() | 创建新的条件变量 |
方法 | 含义 |
---|---|
condition.await() | 等待这个条件 |
signal() | 唤醒 |
signalAll() | 唤醒全部 |
公平锁
默认不公平
通过构造方法实现
java
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** Synchronizer providing all implementation mechanics */
private final Sync sync;
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
条件变量
synchronized中也有条件变量,就是我们讲原理时那个waitSet休息室,当条件不满足时进入waitSet等待
ReentrantLock的条件变量会吧waitSet进行细分,存在多个waitSet
- await前需要获得锁
- await执行后,会释放锁,进入conditionObject等待
- await的线程被唤醒、打断、超时,重新竞争lock锁
- 竞争lock锁成功后,从await后继续执行
java
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Condition condition = lock.newCondition();
Condition condition1 = lock.newCondition();
lock.lock();
try {
condition.await();
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}