ReentrantLock是一个可重入且独占式的锁,该锁支持获取锁时的公平和非公平选择。

公平锁

公平锁遵循FIFO的原则,所有的线程都会顺序执行

获取锁

1
2
3
4
5
6
7
8
9
10
11
12

//加锁
final void lock() {
acquire(1);
}

//调用AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}

是否是获得锁,还是进入队列等待的逻辑在tryAcquire 函数里。

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
protected final boolean tryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();

// 获取state值,state代表前线程获取锁的可重入次数
int c = getState();
/** 如果c为0,判断阻塞队列中是否还有线程,
* 如果不存在,设置state的值,并设置当前线程为独占锁的拥有者
* 如果队列中还存在节点,则将该线程加入到队列中。
**/
if (c == 0) {
//判断队列中是否还存在线程
if (!hasQueuedPredecessors() &&
//设置state值
compareAndSetState(0, acquires)) {
// 设置当前线程为独占锁的拥有者
setExclusiveOwnerThread(current);
//返回ture代表获取锁成功
return true;
}
}
/**
* 如果c不为0,判断独占锁的拥有者是否是当前线程,
* 如果是,则修改state值
**/
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
/**返回 false 代表获取锁失败,
* 则AbstractQueuedSynchronizer类的acquire函数继续往下进行,将该线程加入到队列中。
**/
return false;
}


public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}

释放锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public void unlock() {
sync.release(1);
}

//调用AbstractQueuedSynchronizer
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}

具体的释放逻辑在release中,free代表该锁是否已完全释放锁,如果为true,AbstractQueuedSynchronizer继续执行release,唤醒队列中的下一个节点;
false则该线程继续持有锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//如果当前可重入次数为0 则清空锁持有线程
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);

return free;
}

非公平锁

非公平锁不会关注阻塞队列中是否还有线程,而是直接尝试获取锁,获取不到时在将线程加入到队列中。

获取锁

1
2
3
4
5
6
7
8
9
10
11
12
13
final void lock() {
//修改state的值,修改成功则设值设置当前线程为独占锁的拥有者
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
//调用AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}

非公平锁与公平锁的差别在于当c为0时,不去查询队列的状态,而是直接尝试修改state的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}

final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

非公平锁和共平锁的释放锁逻辑相同。