读写锁概念:
写锁排他,读锁共享。
tryReadLock:
static final int SHARED_SHIFT = 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;
/** Returns the number of shared holds represented in count */
//state的高16位表示读锁
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
/** Returns the number of exclusive holds represented in count */
//state的低16位表示写锁
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
if (exclusiveCount(c) != 0 &&//如果有写锁占了,且该写锁不是当前线程,表示不能获取到读锁
getExclusiveOwnerThread() != current)
return false;
int r = sharedCount(c); //读锁计数器
if (r == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
if (compareAndSetState(c, c + SHARED_UNIT)) {//SHARED_UNIT表示1移到高位后位置
if (r == 0) {
firstReader = current;//放第一个读锁的缓存
firstReaderHoldCount = 1;//放第一个读锁的缓存
} else if (firstReader == current) {
firstReaderHoldCount++; //读锁重入
} else {
HoldCounter rh = cachedHoldCounter;
//if有两种情况:
//1)第一次进来
//2)缓存的HoldCounter不是当前线程的HoldCounter
//则将缓存改为当前线程的Counter
//这里理解就是一个缓存操作,提高执行效率
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;//增加当前线程的计数器
}
return true;
}
}
}
上面可以看到除了和写锁互斥以外,读锁之间并不互斥。所以除了开始判断有没有写锁,之后一路顺畅。
final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c != 0) {
int w = exclusiveCount(c);//获得写锁计数器
if (w == 0 || current != getExclusiveOwnerThread())//如果写锁计数器为0或者不是当前线程,注意前面的if(c!=0)判断,说明有锁,但不是写锁(是读锁)
return false;
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
//走到这里的情况只可能是c==0或者获得锁的线程是当前线程
if (!compareAndSetState(c, c + 1))
return false;
setExclusiveOwnerThread(current);
return true;
}