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的核心源码,就不再说了。