ReentrantLock源码分析
类的继承关系
ReentrantLock实现了Lock接口,Lock接口定义了lock与unlock相关操作,并且还存在newCondition方法,表示生成一个条件。
1
类的内部类
ReentrantLock总共有三个内部类i,并且三个内部类是紧密相关的,下面先看三个类的关系。
说明:ReentrantLock类内部总共存在Sync、NonfairSync、FairSync三个类,NonfairSync与FairSync类继承自Sync类,Sync类继承自AbstractQueuedSynchronizer抽象类。
- Sync类 Sync类的源码如下:
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
Sync类存在如下方法和作用如下:
方法 作用
lock 锁定,并为实现,留给具体子类实现
nonfairTryAcquire 非公平方式获取
tryRelease 试图在共享模式下获取对象状态,此方法应该是查询是否允许它在共享模式下获取对象状态,如果允许,则获取它。
isHeldExclusively 判断资源是否被当前线程占有
newCondition 新生一个条件
getOwner 返回占有资源的线程
getHoldCount 返回状态
isLocked 资源是否被占用
readObject 自定义反序列化逻辑
- NonfairSync类 NonfairSync类继承了Sync类,表示采用非公平策略获取锁,其实现了Sync类中抽象的lock方法,源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
说明:从lock方法的源码可知,每一次都尝试获取锁,而并不会按照公平等待原则进行等待,让等待时间最久的线程获得锁。
- FairSyn类 FairSync也继承了Sync类,表示采用公平策略获取锁,其实现了Sync类中的抽象lock方法,源码如下:
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
说明:跟踪lock方法的源码可知,当资源空闲时,它总是会先判断sync队列是否有等待时间更长的线程,如果存在,则将该线程加入到等待队列的尾部,实现了公平获取原则。其中,FairSync类的lock的方法调用如下,只给出了主要方法。
说明:可以看出只要资源被其他线程占用,该线程就会添加到sync queue中的尾部,而不会先尝试获取资源。这也是和Nonfair最大的区别,NonFair每一次都会尝试去获取资源,如果此时资源恰好被释放,则会被当前线程获取,这就造成了不公平的现象,当获取不成功,再加入队列尾部。
类的属性
ReentrantLock类的sync非常重要,对ReentrantLock类的操作大部分都直接转化为对Sync和AbstractQueuedSynchronizer类的操作。
1
2
3
4
5
6
类的构造函数
- ReentrantLock()型构造函数 默认采用的是非公平锁策略获取锁
1
2
3
4
- ReentrantLock(boolean)型构造函数 可以传递参数确定采用公平策略或者是非公平策略,参数为true表示公平策略,否则,采用非公平策略:
1
2
3
核心函数分析
通过分析ReentrantLock的源码,可知对其操作都转化为对Sync对象的操作,由于Sync继承了AQS,所以基本上都可以转化为对AQS的操作。如将ReentrantLock的lock函数转化为对Sync的lock函数调用,而具体会根据采用的策略的不同调用到Sync的不同子类。
所以可知,在ReentrantLock的背后,是AQS对其服务提供了支持,由于之前我们分析AQS的核心源码,就不再说了。