一、同步器
先来看看读写锁持有的同步器,实现了AQS;读锁和写锁持有同一个Sync
abstract static class Sync extends AbstractQueuedSynchronizer
static final int SHARED_SHIFT = 16;//偏移量
//读锁的基础数,读锁数放在高16位
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;//获取锁的最大数量
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;//独占
//利用位运算将读锁状态放在低16位,读锁状态放在高16位
//读锁数量
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
//写锁数量
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
一、读锁
ReentrantReadWriteLock.ReadLock是ReentrantReadWriteLock的一个静态内部类;
public void lock() {
sync.acquireShared(1);
}
public final void acquireShared(int arg) {
//尝试获取锁
if (tryAcquireShared(arg) < 0)
//获取锁失败后的操作
doAcquireShared(arg);
}
1、tryAcquireShared(int)
//读锁自定义的尝试获取锁的方法
protected final int tryAcquireShared(int unused) {
/*
* Walkthrough:
* 1. If write lock held by another thread, fail.
* 2. Otherwise, this thread is eligible for
* lock wrt state, so ask if it should block
* because of queue policy. If not, try
* to grant by CASing state and updating count.
* Note that step does not check for reentrant
* acquires, which is postponed to full version
* to avoid having to check hold count in
* the more typical non-reentrant case.
* 3. If step 2 fails either because thread
* apparently not eligible or CAS fails or count
* saturated, chain to version with full retry loop.
*/
Thread current = Thread.currentThread();
int c = getState();
// 获取写锁数量判断是否存在写锁,和写锁的线程是否是当前线程
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
// 读是否需要加锁
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
//获取锁成功
if (r == 0) {
//第一个获取读锁
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
//当前线程再次获取读锁
firstReaderHoldCount++;
} else {
//缓存最后一个获取读锁的线程 获取锁个数的计数器
HoldCounter rh = cachedHoldCounter;
// null或者不是当前线程的计数器
if (rh == null || rh.tid != getThreadId(current))
//从ThreadLocal中获取或者初始化
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return 1;
}
return fullTryAcquireShared(current);
}
判断读锁是否应该被阻塞方法readerShouldBlock()
//非公平锁的实现
final boolean readerShouldBlock() {
return apparentlyFirstQueuedIsExclusive();
}
// 如果队列不为空 显然在队列的头部是排他锁;且第二节点不为空且不是共享锁并且不是 //当前线程持有,则读锁无法获取
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
/******公平锁的实现***********/
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
public final boolean hasQueuedPredecessors() {
// 头不等于尾,表示队列至少有2个节点
// 第二节点为null,或者不是当前线程持有
//如果第二节点是当前线程持有,head就是写锁,那么可以尝试获取锁
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
上一步获取失败
//完整版获取共享锁
final int fullTryAcquireShared(Thread current) {
/*
* This code is in part redundant with that in
* tryAcquireShared but is simpler overall by not
* complicating tryAcquireShared with interactions between
* retries and lazily reading hold counts.
*/
HoldCounter rh = null;
// 自旋获取,除非出现获取失败,或者成功;就会一直自旋 知道出现前面两种情况
for (;;) {
int c = getState();
//判断是否获取写锁并且不是当前线程获取(返回-1表示获取失败)
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
// else we hold the exclusive lock; blocking here
// would cause deadlock.
} else if (readerShouldBlock()) {
// 确保我们没有重新获取锁
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.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;
}
}
}
2、doAcquireShared(int)
查看AQS 共享锁部分AQS源码解析
3、releaseShared(int)
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
//唤醒下个节点
doReleaseShared();
return true;
}
return false;
}
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--;
} else {
HoldCounter rh = cachedHoldCounter;
//从ThreadLocal中获取计数器
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
int count = rh.count;
if (count <= 1) {
readHolds.remove();
if (count <= 0)
throw unmatchedUnlockException();
}
--rh.count;
}
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
if (compareAndSetState(c, nextc))
// Releasing the read lock has no effect on readers,
// but it may allow waiting writers to proceed if
// both read and write locks are now free.
return nextc == 0;
}
}
二、写锁
主要实现了AQS的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");
// 锁已被自己获取,重入
setState(c + acquires);
return true;
}
//非公平锁永远false,非公平必须按队列顺序,所以需要判断队列是否为空,或者第二节点是否是当前线程持有,才有资格尝试获取锁
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
我们来看看公平锁的writeShouldBlock
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
public final boolean hasQueuedPredecessors() {
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}