一、ReentrantLock重入锁基本概念
ReentrantLock,重入锁,是JDK5中添加在并发包下的一个高性能的工具。顾名思义,ReentrantLock支持重入功能,即同一个线程在未释放锁的情况下可以重复获取锁,因此,重入的前提必须是同一个线程,后面会基于源码展示重入功能具体是如何实现的。
本文内容将以介绍ReentrantLock的基本功能为主体,辅以相应源码的剖析,使读者深入记忆ReentrantLock锁的各种机制,以及实现原理。
二、ReentrantLock与Synchronized的区别
对比项 | Synchronized | ReentrantLock |
---|---|---|
性能 | 相对较差 | 优于synchronized 20%左右 |
公平性 | 只支持非公平锁 | 同时支持公平锁与非公平锁 |
尝试获取锁 | 不支持,一旦到了同步块,且没有获取到锁,就阻塞在这里 | 支持,通过tryLock方法实现,可通过其返回值判断是否成功获取锁,所以即使获取锁失败也不会阻塞在这里 |
超时的获取锁 | 不支持,如果一直获取不到锁,就会一直等待下去 | 支持,通过tryLock(time, TimeUnit)方法实现,如果超时了还没获取锁,就放弃获取锁,不会一直阻塞下去 |
是否可响应中断 | 不支持,不可响应线程的interrupt信号 | 支持,通过lockInterruptibly方法实现,通过此方法获取锁之后,线程可响应interrupt信号,并抛出InterruptedException异常 |
等待条件的支持 | 支持,通过wait、notify、notifyAll来实现 | 支持,通过Conditon接口实现,支持多个Condition,比synchronized更加灵活 |
从上面的表格中可以看出为什么要引入ReentrantLock锁了,因为其在很多方面都比Synchronized锁更灵活,当存在大量线程竞争锁时,ReentrantLock的性能也要优于synchronized。因此,学好ReentrantLock锁就更有必要了。
三、ReentrantLock公平锁与非公平锁
上面说到了ReentrantLock锁支持两种实现方式,即公平锁与非公平锁。
我们先来看一下ReentrantLock的具体实现架构图:
ReentrantLock锁实现了Lock接口,里面具体锁的实现使用了抽象内部类Sync。Sync有两个实现类,NonfairSync和FairSync,即公平锁与非公平锁。这两个也是ReentrantLock的内部类,继承自Sync。
源码中ReentrantLock实例化的过程:
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
在创建ReentrantLock锁对象的时候,默认的无参构造函数创建的是非公平锁,即NonfairSync。构造函数中可以指定一个boolean变量,即公平性,可以根据这个参数创建公平锁或者非公平锁。
知道了ReentrantLock内部创建的过程,那么什么是公平锁?什么是非公平锁呢?
如果是公平锁,多个线程之间获取锁的时候要排队,依次获取锁;如果是不公平锁,多个