ReentrantReadWriteLock的公平性体现在Sync的两个子类NonfairSync和FairSync重写的Sync中的两个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Returns true if the current thread, when trying to acquire
* the read lock, and otherwise eligible to do so, should block
* because of policy for overtaking other waiting threads.
* 如果当前线程在尝试获取读锁时阻塞,并且由于策略原因无法超过其他等待的线程,
* 因此有资格阻塞读锁,则返回true。
*/
abstract boolean readerShouldBlock();

/**
* Returns true if the current thread, when trying to acquire
* the write lock, and otherwise eligible to do so, should block
* because of policy for overtaking other waiting threads.
* 如果当前线程在尝试获取写锁时阻塞,并且由于策略原因无法超过其他等待的线程,
* 因此有资格这样做,则返回true。
*/
abstract boolean writerShouldBlock();

readerShouldBlock方法使用的地方为共享模式锁的获取,writerShouldBlock使用的地方为独占模式锁的获取。

NonfairSync

1
2
3
4
5
final boolean writerShouldBlock() {
// writers can always barge
//非公平模式下,写锁的获取,当发生阻塞的时候,返回false
return false;
}

写锁在非公平模式,在非重入的前提下永远获取锁失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
final boolean readerShouldBlock() {
/* As a heuristic to avoid indefinite writer starvation,
* block if the thread that momentarily appears to be head
* of queue, if one exists, is a waiting writer. This is
* only a probabilistic effect since a new reader will not
* block if there is a waiting writer behind other enabled
* readers that have not yet drained from the queue.
* 作为一种避免无限writer饥饿的启发式方法,
* 如果暂时出现队列头的线程(如果存在)是一个正在等待的writer,则阻塞。
* 这只是一种概率效应,因为如果在其他启用的reader后面有一个等待的writer,
* 而这些reader还没有从队列中删除,则新reader不会阻塞。
*/
return apparentlyFirstQueuedIsExclusive();
}
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}

读锁在非公平模式下,同步队列中最少为两个节点,且当前节点不是共享模式,且节点的线程不为null,就阻塞获取锁。

FairSync

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}

final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
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());
}

公平模式下,读锁与写锁都要看自己是不是将要获取锁的同步队列节点,如果不是,就阻塞。