参考:
Java
并发编程的艺术
JDK版本
:AdoptOpenJDK 11.0.2+9
ReentrantLock
是可重入的独占锁,特征如下:
- 只有一个线程可以获取锁。
- 支持一个线程对共享资源的重复加锁。
- 支持获取锁时候的公平性和非公平性选择。
1 可重入
可重入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞。
ReentrantLock
实现了可重入锁的逻辑,解决两个关键问题:
- 支持线程再次获取锁。 锁需要识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取锁。
- 锁的最终释放。 通过计数器记录锁被重复获取的次数,而锁被释时,计数自减,当计数等于
0
时表示锁成功释放。
1.1 可重入获取锁
ReentrantLock
在公平锁和非公平锁(默认实现)的实现中都实现了锁的可重入性。
以非公平锁为例,源码如下:
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 获取同步状态的值
int c = getState();
// 如果还没有线程获取同步状态,c就等于0
if (c == 0) {
// 设置同步状态的值
if (compareAndSetState(0, acquires)) {
// 如果成功,设置独占模式下获得锁的是哪个线程
setExclusiveOwnerThread(current);
// 返回true,表示成功获取了锁
return true;
}
}
// 如果当前线程就是获取了锁的线程,重入
else if (current == getExclusiveOwnerThread()) {
// 计算同步状态要更新的值
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 设置同步状态的值