ReentrantLock 公平锁与非公平锁
SunRan

实例化

在实例化 ReentrantLock 的时候可以加一个构造参数。

1
2
3
4
5
// 传true时为公平锁
ReentrantLock lock = new ReentrantLock(true);

// 非公平锁
ReentrantLock lock = new ReentrantLock();

当然他们的构造方法也是不一样的

构造方法

1
2
3
4
5
6
7
8
9
// fair为true时为公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}

// 默认非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}

此事我们发现 ReentrantLock 为了应对公平锁与非公平锁实现了两个类: FairSync 和 NonfairSync 。他们都是继承于 Sync 类。

lock

我们找到 FairSyncNonfairSync 类的 lock 方法,发现区别还是很明显的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
}


static final class NonfairSync extends Sync {
final void lock() {
// 发现非公平锁比公平锁多了一步
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
}

公平锁在执行 lock 方法时会直接执行 acquire 方法,而非公平锁会先尝试替换一下状态,如果成功则设置当前线程为所有者。

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
// 公平锁
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

// 非公平锁
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;
}

貌似很多,是否公平的关键只是一个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 非公平
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}

// 公平
if (c == 0) {
// 多了一个hasQueuedPredecessors
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}

hasQueuedPredecessors

翻译过来就是队列是否有前节点。

1
2
3
4
5
6
7
8
9
10
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}

头节点不是尾节点 且 ( 头节点的下一个节点不为空 或者 头节点的下一个节点不是当前节点 )

  • 本文标题:ReentrantLock 公平锁与非公平锁
  • 本文作者:SunRan
  • 创建时间:2022-01-06 15:51:45
  • 本文链接:https://lksun.cn/2022/01/06/ReentrantLock 公平锁与非公平锁/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论