ReentrantReadWriteLock 读写锁
构造函数
与ReentrantLock相类似, 其自定义同步器Sync分为公平锁FairSync与非公平锁NonfairSync的两种.
默认为NonfairSync
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean var1) {
this.sync = (ReentrantReadWriteLock.Sync)(var1?new ReentrantReadWriteLock.FairSync():new ReentrantReadWriteLock.NonfairSync());
this.readerLock = new ReentrantReadWriteLock.ReadLock(this);
this.writerLock = new ReentrantReadWriteLock.WriteLock(this);
}
同步状态
同步状态表示锁被一个线程重复获取的次数. 而ReentrantReadWriteLock的自定义同步器Sync需要在同步状态(一个整型变量)上维护多个读线程和一个写线程的状态. 读写锁通过将该整型变量”按位切割使用”, 切分为两个部分, 高16位表示读, 低16位表示写
//ReentrantReadWriteLock.java: ReentrantReadWriteLock.Sync
// 获取写同步锁状态
static int exclusiveCount(int var0) {
return var0 & '\uffff';
}
// 获取读同步锁状态
static int sharedCount(int var0) {
return var0 >>> 16;
}
WriteLock 写锁
获取
获取锁的全过程: ReentrantReadWriteLock.WriteLock.lock() –> this.sync.acquire(1) (即 AbstractQueueSynchronizer.acquire(int var1)) –> ReentrantReadWriteLock.WriteLock.tryAcquire(1)
- 获取写锁成功: ReentrantReadWriteLock.WriteLock.tryAcquire(1)返回true, AbstractQueueSynchronizer.acquireQueued()返回true
- 获取写锁阻塞: ReentrantReadWriteLock.WriteLock.tryAcquire(1)返回false, AbstractQueueSynchronizer.acquireQueued()阻塞, 自旋锁
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
public void lock() {
this.sync.acquire(1);
}
this.sync为ReentrantReadWriteLock自定义同步器Sync的实例(也是ReentrantReadWriteLock实例的成员变量), 是AbstractQueueSynchronizer的子类.
// AbstractQueueSynchronizer.java AbstractQueueSynchronizer
public final void acquire(int var1) {
if(!this.tryAcquire(var1) && this.acquireQueued(this.addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE), var1)) {
selfInterrupt();
}
}
由于this.sync重写了父类的tryAcquire()等方法, 所以this.tryAcquire
会调用重写后的方法
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
protected final boolean tryAcquire(int var1) {
Thread var2 = Thread.currentThread();
int var3 = this.getState();
int var4 = exclusiveCount(var3); // 获取写状态
if(var3 != 0) {
// 支持重进入
if(var4 != 0 && var2 == this.getExclusiveOwnerThread()) {
if(var4 + exclusiveCount(var1) > '\uffff') {
throw new Error("Maximum lock count exceeded");
} else {
this.setState(var3 + var1);
return true;
}
} else {
//存在读锁或者当前获取线程不是已经获取写锁的线程
// var4 == 0 || var2 != this.getExclusiveOwnerThread()
return false;
}
} else if(!this.writerShouldBlock() && this.compareAndSetState(var3, var3 + var1)) { // 当前无线程获取写锁
this.setExclusiveOwnerThread(var2);
return true;
} else {
return false;
}
}
AbstractQueueSynchronizer.acquire():
释放
释放的全过程: ReentrantReadWriteLock.WriteLock.unlock() –> this.sync.release(1) (即 AbstractQueueSynchronizer.release(int var1)) –> ReentrantReadWriteLock.WriteLock.tryRelease
只有获取写锁线程(同步队列中头节点)全部释放写锁后(ReentrantReadWriteLock.WriteLock.tryRelease返回true), 才会唤醒同步队列中头节点的后继节点(AbstractQueueSynchronizer.release中断unparkSuccessor)
跟ReentrantLock释放锁的逻辑是一样.
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
public void unlock() {
this.sync.release(1);
}
// AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
public final boolean release(int var1) {
if(this.tryRelease(var1)) {
AbstractQueuedSynchronizer.Node var2 = this.head;
// waitStatus为0说明是初始化的空队列
if(var2 != null && var2.waitStatus != 0) {
this.unparkSuccessor(var2); // 唤醒同步队列中头节点的后继节点
}
return true;
} else {
return false;
}
}
因为写锁支持重进入,所以只有多次获取了写锁的线程持有的写锁完全是否完毕才会返回true
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
protected final boolean tryRelease(int var1) {
if(!this.isHeldExclusively()) {
throw new IllegalMonitorStateException();
} else {
int var2 = this.getState() - var1;
boolean var3 = ( exclusiveCount(var2) == 0 );
if(var3) {
// 写锁完全释放完毕(=0), 因为写锁支持重进入
this.setExclusiveOwnerThread((Thread)null);
}
// 减少写锁次数
this.setState(var2);
return var3;
}
}
ReadLock 读锁
获取
获取读锁全过程: ReentrantReadWriteLock.ReadLock.lock() –> this.sync.acquireShared(1); (即, AbstractQueueSynchronizer.acquireShared)
- 获取成功: this.sync.acquireShared(1)马上返回
- 获取阻塞: 获取读锁失败(ReentrantReadWriteLock.Sync.tryAcquireShared(1) < 0) –> 进入同步队列等待(AbstractQueueSynchronizer.doAcquireShared(1)), 只有同步队列中该线程的前驱节点为同步队列的头节点, 并且能够成获取读锁(ReentrantReadWriteLock.Sync.tryAcquireShared(1) > 0)
//ReentrantReadWriteLock.Java: ReentrantReadWriteLock.ReadLock
public void lock() {
this.sync.acquireShared(1);
}
AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
public final void acquireShared(int var1) {
if(this.tryAcquireShared(var1) < 0) { // 获取读锁失败则进入同步队列等待
this.doAcquireShared(var1);
}
}
//ReentrantReadWriteLock.Java: ReentrantReadWriteLock.Sync
protected final int tryAcquireShared(int var1) {
Thread var2 = Thread.currentThread();
int var3 = this.getState();
// 写锁已被其他线程获取
if(exclusiveCount(var3) != 0 && this.getExclusiveOwnerThread() != var2) {
return -1;
} else {
int var4 = sharedCount(var3);
// 读锁处于非阻塞状态 && 读锁没有达最大值 && 修改读锁状态成功(读锁加1: var3 + 65536 <==> var + (1<<16) )
if(!this.readerShouldBlock() && var4 < '\uffff' && this.compareAndSetState(var3, var3 + 65536)) {
// 读锁首次获取
if(var4 == 0) {
this.firstReader = var2;
this.firstReaderHoldCount = 1;
} else if(this.firstReader == var2) { // firstReader线程再次获得读锁
++this.firstReaderHoldCount;
} else { // 非firstReader线程
// 保存当前线程读取锁的次数
ReentrantReadWriteLock.Sync.HoldCounter var5 = this.cachedHoldCounter; // cachedHoldCounter存储当前线程获取读锁的次数
// 3. 当前线程非首次获取读锁
if(var5 != null && var5.tid == ReentrantReadWriteLock.getThreadId(var2)) {
if(var5.count == 0) {
this.readHolds.set(var5);
}
} else {
// 1. 当前线程首次获取读锁, 新建cachedHoldCounter (ThreadLocal: get() --> setInitialValue() --> createMap())
this.cachedHoldCounter = var5 = (ReentrantReadWriteLock.Sync.HoldCounter)this.readHolds.get();
}
// 2. 更新当前线程获取读锁的次数
++var5.count;
}
return 1;
} else {
return this.fullTryAcquireShared(var2);
}
}
}
//AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
private void doAcquireShared(int var1) {
// 将当前节点加入同步队列
AbstractQueuedSynchronizer.Node var2 = this.addWaiter(AbstractQueuedSynchronizer.Node.SHARED);
boolean var3 = true;
try {
boolean var4 = false;
while(true) {
AbstractQueuedSynchronizer.Node var5 = var2.predecessor();
if(var5 == this.head) { // 前驱节点为头节点
int var6 = this.tryAcquireShared(var1);
if(var6 >= 0) { // 获取读锁成功, 否则自旋等待读锁
// 更新头节点, 会往后面结点传播唤醒的操作,保证剩下等待的线程能够尽快 获取到剩下的许可。
this.setHeadAndPropagate(var2, var6);
var5.next = null;
if(var4) {
selfInterrupt();
}
var3 = false;
return;
}
}
if(shouldParkAfterFailedAcquire(var5, var2) && this.parkAndCheckInterrupt()) {
var4 = true;
}
}
} finally {
if(var3) { // 获取读锁失败, 取消获取读锁
this.cancelAcquire(var2);
}
}
}
释放
ReentrantReadWriteLock.ReadLock.unlock() –> this.sync.releaseShared(1) 即, AbstractQueueSynchronizer.releaseShared(1) –> ReentrantReadWriteLock.Sync.tryReleaseShared() –>(倘若线程所持有的所有读锁都释放完毕) AbstractQueueSynchronizer.doReleaseShared()
- 读锁释放成功: 当前线程所持有的所有读锁都释放完毕, this.sync.releaseShared(1)返回true; 倘若知只是释放了其中一个读锁, this.sync.releaseShared(1)返回false
- 读锁释放重试: AbstractQueueSynchronizer.doReleaseShared()
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.ReadLock
public void unlock() {
this.sync.releaseShared(1);
}
只有当前线程所持有的所有读锁都释放完毕, 才会返回true
// AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
public final boolean releaseShared(int var1) {
if(this.tryReleaseShared(var1)) { // 当前线程所持有的所有读锁都释放完毕, 当前队列从同步队列的移出, 修改同步队列头节点
this.doReleaseShared(); // 唤醒同步队列的后继节点
return true;
} else {
return false;
}
}
只有当前线程所持有的所有读锁都释放完毕, 才会返回true
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.Sync
protected final boolean tryReleaseShared(int var1) {
Thread var2 = Thread.currentThread();
int var4;
// 当前线程的读锁状态
if(this.firstReader == var2) {
if(this.firstReaderHoldCount == 1) {
this.firstReader = null;
} else {
--this.firstReaderHoldCount;
}
} else {
ReentrantReadWriteLock.Sync.HoldCounter var3 = this.cachedHoldCounter;
if(var3 == null || var3.tid != ReentrantReadWriteLock.getThreadId(var2)) {
var3 = (ReentrantReadWriteLock.Sync.HoldCounter)this.readHolds.get();
}
var4 = var3.count;
// 当前线程所有读锁都已经释放, 从读锁的同步队列中移出
if(var4 <= 1) {
this.readHolds.remove();
if(var4 <= 0) {
throw this.unmatchedUnlockException();
}
}
--var3.count;
}
int var5;
do {
var5 = this.getState();
var4 = var5 - 65536; // 修改当前读锁状态: var5 - (1<<16)
} while(!this.compareAndSetState(var5, var4));
return var4 == 0;
}
//AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
private void doReleaseShared() {
while(true) {
AbstractQueuedSynchronizer.Node var1 = this.head;
if(var1 != null && var1 != this.tail) {
int var2 = var1.waitStatus;
if(var2 == -1) { // 1. 后继节点等待唤醒
if(!compareAndSetWaitStatus(var1, -1, 0)) {
continue;
}
this.unparkSuccessor(var1); // 2. 唤醒后继节点
} else if(var2 == 0 && !compareAndSetWaitStatus(var1, 0, -3)) {
// 3. 后续结点会传播唤醒的操作
continue;
}
}
if(var1 == this.head) { // 当前节点为同步对列的头节点
return;
}
}
}