ReentrantReadWriteLock
在ReentrantReadWriteLock中维护了两个锁,一个读锁,一个写锁。它的特性是。读锁在同一时刻允许多个线程访问。但是在写锁被访问时,所有访问读锁的线程和其它访问写锁的线程都会被阻塞。
在读多于写的情况下,读写锁能够提供比排他锁更好的并发性和吞吐量。
ReadLock
readLock:时序图
readLock:源码分析
tryAcquiredShared(int unused)
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
// c为锁的状态位,高16位表示共享锁的数量,低16位表示独占锁的数量
int c = getState();
// exclusiveCount(c) 取低16位的值,也就是写锁状态位:不等于0表示写锁被占用
// getExclusiveOwnerThread() != current 判断拥有锁的线程是不是当前线程
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
// 返回 -1 表示获取锁失败
return -1;
// 获取高16位的值,即读锁的状态位
int r = sharedCount(c);
// readerShouldBlock ---见下文
// r < MAX_COUNT 判断读锁数量是否超过系统默认值
// compareAndSetState cas修改高16位的读锁状态,即获取读锁
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
// 首次获取读锁
if (r == 0) {
// 缓存首次获取读锁的线程以及重入次数
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
// cachedHoldCounter---最后获取锁的线程的读锁重入次数
HoldCounter rh = cachedHoldCounter;
// readHolds是缓存了当前线程的读锁重入次数的ThreadLocal
// 当前线程自然是最后获取锁的线程,故将当前线程的holdCounter赋给cachedHoldCounter
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
// 缓存当前线程的holdCounter
// fullTryAcquireShared()方法中,
// 获取读锁失败的线程会执行:readHolds.remove(),故此时需要重新设置
readHolds.set(rh);
rh.count++;
}
return 1;
}
// step two : 获取读锁失败后,重新获取
return fullTryAcquireShared(current);
}
fullTryAcquireShared(current);
final int fullTryAcquireShared(Thread current) {
// rh : 当前线程的锁计数器
HoldCounter rh = null;
for (;;) {
int c = getState();
if (exclusiveCount(c) != 0) {
// 判断是否有其它线程占用读锁--是:读锁获取失败、否:锁降级
if (getExclusiveOwnerThread() != current)
return -1;
// else we hold the exclusive lock; blocking here
// would cause deadlock.
} else if (readerShouldBlock()) {
// Make sure we're not acquiring read lock reentrantly
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
} else {
if (rh == null) {
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
if (rh.count == 0)
// 线程阻塞之前,清空readHolds
readHolds.remove();
}
}
if (rh.count == 0)
return -1;
}
}
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
if (compareAndSetState(c, c + SHARED_UNIT)) {
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
if (rh == null)
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
cachedHoldCounter = rh; // cache for release
}
return 1;
}
}
}
readerShouldBlock
FairSync
final boolean readerShouldBlock() {
// 当前线程不是同步队列头结点的next节点(head.next) --阻塞当前线程
return hasQueuedPredecessors();
}
NonFairSync
final boolean readerShouldBlock() {
// 同步队列中的第一个线程若是以独占模式获取锁(写锁)-即获取写锁
// 那么当前获取读锁的线程需要阻塞,让队列中的第一个线程先执行
return apparentlyFirstQueuedIsExclusive();
}
WriteLock
writeLock时序图
writeLock源码分析
tryAcquire
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
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)
throw new Error("Maximum lock count exceeded");
// Reentrant acquire
// 获得锁,增加重入次数
setState(c + acquires);
return true;
}
// c=0 当前无线程获得写锁
// writerShouldBlock()---判断是否符合 公平锁/非公平锁 策略
// compareAndSetState cas尝试获得锁
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
// 写锁独占锁
setExclusiveOwnerThread(current);
return true;
}