開(kāi)篇
?ReentrantReadWriteLock是Lock的另一種實(shí)現(xiàn)方式,我們已經(jīng)知道了ReentrantLock是一個(gè)排他鎖,同一時(shí)間只允許一個(gè)線程訪問(wèn),而ReentrantReadWriteLock允許多個(gè)讀線程同時(shí)訪問(wèn),但不允許寫(xiě)線程和讀線程、寫(xiě)線程和寫(xiě)線程同時(shí)訪問(wèn)。
?相對(duì)于排他鎖,提高了并發(fā)性。在實(shí)際應(yīng)用中,大部分情況下對(duì)共享數(shù)據(jù)(如緩存)的訪問(wèn)都是讀操作遠(yuǎn)多于寫(xiě)操作,這時(shí)ReentrantReadWriteLock能夠提供比排他鎖更好的并發(fā)性和吞吐量。
?這個(gè)系列主要是從源碼層面講解ReentrantReadWriteLock,總共分為3篇,歡迎訂閱。
- ReentrantReadWriteLock的數(shù)據(jù)結(jié)構(gòu)介紹
- java源碼 - ReentrantReadWriteLock讀鎖介紹
- java源碼 - ReentrantReadWriteLock寫(xiě)鎖介紹
ReentrantReadWriteLock類(lèi)
?ReentrantReadWriteLock類(lèi)包含三個(gè)核心變量:
readerLock:讀鎖。
writerLock:寫(xiě)鎖。
sync:可以為公平鎖FairSync 或 非公平鎖NonfairSync。
?ReentrantReadWriteLock類(lèi)的構(gòu)造函數(shù)執(zhí)行以下幾件事情:
新建鎖對(duì)象賦予ReentrantReadWriteLock的sync對(duì)象。
將ReentrantReadWriteLock對(duì)象作為this參數(shù)創(chuàng)建讀鎖ReadLock。
將ReentrantReadWriteLock對(duì)象作為this參數(shù)創(chuàng)建寫(xiě)鎖WriteLock。
在writerLock和ReadLock構(gòu)造函數(shù)中將ReentrantReadWriteLock的sync對(duì)象賦值為自身的sync對(duì)象,讀寫(xiě)鎖的操作其實(shí)用的就是ReentrantReadWriteLock的sync對(duì)象。
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable {
private static final long serialVersionUID = -6992448646407690164L;
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
ReadLock類(lèi)
- ReadLock的構(gòu)造函數(shù)入?yún)镽eentrantReadWriteLock對(duì)象,通過(guò)將ReentrantReadWriteLock對(duì)象的sync對(duì)象賦值給ReadLock的Sync。
- ReadLock的lock和unlock操作都通過(guò)sync對(duì)象來(lái)實(shí)現(xiàn)加鎖和解鎖
public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
public void lock() {
sync.acquireShared(1);
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean tryLock() {
return sync.tryReadLock();
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.releaseShared(1);
}
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
WriteLock類(lèi)
- WriteLock的構(gòu)造函數(shù)入?yún)镽eentrantReadWriteLock對(duì)象,通過(guò)將ReentrantReadWriteLock對(duì)象的sync對(duì)象賦值給ReadLock的Sync。
- WriteLock的lock和unlock操作都通過(guò)sync對(duì)象來(lái)實(shí)現(xiàn)加鎖和解鎖
public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
public void lock() {
sync.acquire(1);
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock( ) {
return sync.tryWriteLock();
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
public int getHoldCount() {
return sync.getWriteHoldCount();
}
}
公平鎖和非公平鎖類(lèi)定義
- 公平鎖FairSync和非公平鎖NonfairSync屬于ReentrantReadWriteLock內(nèi)部定義類(lèi),繼承自Sync類(lèi)。
- Sync類(lèi)繼承自AbstractQueuedSynchronizer類(lèi),Sync類(lèi)有一些核心的變量已經(jīng)加注釋。
-
AQS的state變量32位分開(kāi)高16位為讀狀態(tài),低16位為寫(xiě)狀態(tài)。
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -8159625535654395037L;
final boolean writerShouldBlock() {
return false; // writers can always barge
}
final boolean readerShouldBlock() {
return apparentlyFirstQueuedIsExclusive();
}
}
static final class FairSync extends Sync {
private static final long serialVersionUID = -2274990926593161451L;
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L;
static final int SHARED_SHIFT = 16;
// 高16位記錄讀狀態(tài)
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
// 低16位記錄寫(xiě)狀態(tài)
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
static final class HoldCounter {
int count = 0;
// Use id, not reference, to avoid garbage retention
final long tid = getThreadId(Thread.currentThread());
}
static final class ThreadLocalHoldCounter
extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter();
}
}
private transient ThreadLocalHoldCounter readHolds;
private transient HoldCounter cachedHoldCounter;
private transient Thread firstReader = null;
private transient int firstReaderHoldCount;
Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState()); // ensures visibility of readHolds
}
}
