ReentrantLock源码阅读

参考kangjianwei大佬的LearningJDK

概述

类图

20190906160805.png

获得锁操作委托给继承了AQS的内部类Sync
FairSync和NonfairSync继承自Sync,分别实现公平和非公平的tryAcquire方法

调用解释

当调用reentrantLock().lock()时,调用sync.aquire(1),即aqs.aquire(1),然后aqs.tryAquire(),实际上是fairSync.tryAcquire()nonfairSync.tryAcquire(),即sync.fairTryAquire()sync.nonfairTryAquire(),尝试获取锁获取不到的话,则aqs.addWaiter(),在同步队列中排队,之后aqs.acquireQueued()从队列中申请,如果申请不到的话,则aqs.selfInterrupt(),阻塞线程.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
// 获取申请锁的线程
final Thread current = Thread.currentThread();

// 当前许可证数量
int c = getState();

// 如果锁没有被任何线程占用
if(c == 0) {
// 发现锁空闲时,不管【同步队列】中有没有人抢锁,该线程直接尝试抢锁,这也是"非公平"所在
// 尝试更新许可证数量为acquires,返回true代表更新成功,即成功抢到了锁
if(compareAndSetState(0, acquires)) {
// 设置当前线程为<占有者线程>
setExclusiveOwnerThread(current);
return true;
}
} else {
/* 至此,说明锁已被占用 */

// 如果当前线程不是锁的占用者,直接返回false,代表抢锁失败,该线程需要去排队
if(current != getExclusiveOwnerThread()) {
return false;
}

/* 至此,说明当前线程就是占用锁的线程,则需要再次持有锁,累计许可证数量,这也是"可重入"的含义 */

// 更新许可证数量
int nextc = c + acquires;
if(nextc<0) {
// 溢出
throw new Error("Maximum lock count exceeded");
}
setState(nextc);

return true;
}

return false;
}

// 申请一次公平锁,返回值代表锁是否申请成功
final boolean fairTryAcquire(int acquires) {
// 获取申请锁的线程
final Thread current = Thread.currentThread();

// 当前许可证数量
int c = getState();

// 如果锁没有被任何线程占用
if(c == 0) {
/* 发现锁空闲时,需要检查有没有其他线程在排队,如果没有其他人在队首,才尝试抢锁,这也是"公平"所在 */

// 判断【|同步队列|】的队头是否还有其他(非当前线程)的线程在排队
if(!hasQueuedPredecessors()) {
// 尝试更新许可证数量为acquires,返回true代表更新成功,即成功抢到了锁
if(compareAndSetState(0, acquires)){
// 设置当前线程为<占有者线程>
setExclusiveOwnerThread(current);
return true;
}
}
} else {
/* 至此,说明锁已被占用 */

// 如果当前线程不是锁的占用者,直接返回false,代表抢锁失败,该线程需要去排队
if(current != getExclusiveOwnerThread()) {
return false;
}

/* 至此,说明当前线程就是占用锁的线程,则需要再次持有锁,累计许可证数量,这也是"可重入"的含义 */

// 更新许可证数量
int nextc = c + acquires;
if(nextc<0) {
// 溢出
throw new Error("Maximum lock count exceeded");
}
setState(nextc);

return true;
}

return false;
}

nonfairTryAcquire和fairTryAcquire区别在于fairTryAcquire判断了是否有正在排队的其他线程