AQS系列之AbstractQueuedSynchronizer基础分析
AQS系列之以排斥锁分析
AQS系列之共享锁解析
AQS系列之共享锁的应用解析:Semaphore
AQS系列之共享锁的应用解析:CountDownLatch
AQS系列之排斥锁的应用解析:ReentrantLock
AQS系列之排斥锁和共享锁的结合:ReentrantReadWriteLock
AQS系列之排斥锁和共享锁的结合:ReentrantReadWriteLock
一、简介
ReentrantReadWriteLock即可重入读写锁,其同时应用了共享锁和排斥锁,写锁使用排斥锁,读锁使用共享锁,从而实现读读共享,读写互斥,写写互斥。
1. Sync
ReentrantReadWriteLock作为锁的一种,同样有公平锁和非公平锁两种子类进行实现。
2. state
作为读写锁的Sync的state,相比其他几个AQS应用类里稍微复杂一点,是一个32位的二进制数,分成两部分,高16位用于共享锁,表示持有锁的线程数;低16位用于排斥锁,表示锁重入次数。。
作为锁
3. ReadLock和WriteLock
ReadLock和WriteLock是ReentrantReadWriteLock的内部类,都实现了Lock接口,分别表示读锁和写锁,用老控制读和写操作,
使用中,需要通过调用public ReentrantReadWriteLock.ReadLock readLock()和public ReentrantReadWriteLock.WriteLock writeLock()获取到对应的读锁和写锁,然后进行lock和unlock进行锁的获取和释放
4. 构造方法
同样的两个构造方法,一个参数为公平策略的构造器,一个无参构造器(默认非公平锁)。
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
可以看到,根据公平策略new一个对应的Sync,然后赋给读锁和写锁,所以读写锁的公平策略必然是一致的。
二. 写锁
1. 获取写锁
public void lock() {
sync.acquire(1);
}
和Reentrant的lock方法一样,通过固定的Sync#acquire(1)实现。
protected final boolean tryAcquire(int acquires) {
/*
* Walkthrough:
* 1. If read count nonzero or write count nonzero
* and owner is a different thread, fail.
* 2. If count would saturate, fail. (This can only
* happen if count is already nonzero.)
* 3. Otherwise, this thread is eligible for lock if
* it is either a reentrant acquire or
* queue policy allows it. If so, update state
* and set owner.
*/
Thread current = Thread.currentThread();
int c = getState();
//与运算取低16位
int w = exclusiveCount(c);
if (c != 0) {
// (Note: if c != 0 and w == 0 then shared count != 0)
//有读锁 || 非当前线程
if (w == 0 || current != getExclusiveOwnerThread())
return false;
if (w + exclusiveCount(acquires) > MAX_COUNT)
t