前言
通过阅读ReentrantReadWriteLock的源码我们会发现ReentrantReadWriteLock内部通过AbstractQueuedSynchronizer来实现同步语义,在ReentrantReadWriteLock中拥有读锁与写锁。读锁是一种共享锁,允许多个线程同时获取锁,写锁是一种独占锁,同一时刻只允许一个线程获取。如果在读多写少的情况下,利用ReentrantReadWriteLock很容易造成饥饿问题。
饥饿问题:ReentrantReadWriteLock实现了读写分离,想要获取读锁就必须确保当前没有其他任何读写锁了,但是一旦读操作比较多的时候,想要获取写锁就变得比较困难了,因为当前有可能会一直存在读锁。而无法获得写锁。
正文
当我们创建一个ReentrantReadWriteLock对象时,默认是非公平性。如果设置ReentrantReadWriteLock为公平性就不会存在饥饿问题,公平性获取锁会让等待最长时间的线程获取锁,只要获取写锁的线程等待的时间足够长,就一定会获取到锁。因此我们重点需要关注非公平性竞争。
下面的代码是饥饿问题的关键。
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -8159625535654395037L;
final boolean writerShouldBlock() {
return false; // writers can always barge
}
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