java.util.concurrent.locks.ReentrantReadWriteLock
state高16位表示共享锁; state低16位表示独占锁。
共享锁和独占锁共用一个AQS对象, 共用同一个锁同步队列
共享锁加锁
- 当前只有共享锁
线程A第一次获取锁
state
0000 0000 0000 0001 0000 0000 0000 0000
相当于 0001(1)
线程A第二次获取锁
state
0000 0000 0000 0010 0000 0000 0000 0000
相当于 0010(2)
类推 0011(3), 0100(4)
state高16位表示共享锁
state低16位表示独占锁
如果共享锁可以获取成功, 则不用加入到锁同步队列; 否则, 加入到锁同步队列。
state高16位记录获取锁的次数, 不管什么线程, 只要是获取了一次共享锁, 则state高16位就加1, 比如1,2 , 3, ...等
static final int SHARED_SHIFT = 16;
// 0000 0000 0000 0001 0000 0000 0000 0000
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
// 0000 0000 0000 0000 1111 1111 1111 1111
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
// 0000 0000 0000 0000 1111 1111 1111 1111
//state 低16位表示独占锁
// state 高16位表示共享锁
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
// status!=0 表示锁被占用
// 并且锁不是被当前线程占用的
// 获取锁失败, 返回-1, 并退出方法
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) { // 锁不空闲且被当前线程占据,并且firstReader是当前线程。
firstReaderHoldCount++;
} else { // 锁不空闲且被当前线程占据,并且firstReader不是当前线程。
// cachedHoldCounter
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
// 保存非首次的最后一次的获取共享锁的线程
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0) // 释放共享锁, count递减
readHolds.set(rh); //替换
rh.count++; // 非首次的获取共享锁的线程,每次获取共享锁都会加1
}
return 1;
}
return fullTryAcquireShared(current); //cas失败,则自旋获取共享锁。
}
// static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// EXCLUSIVE_MASK 0000 0000 0000 0000 1111 1111 1111 1111
// 返回了count
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
// c右移16位
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
// 自旋获取共享锁
final int fullTryAcquireShared(Thread current) {
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.remove();
}
}
if (rh.count == 0)
return -1;
}
}
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 也第一遍获取共享锁的逻辑一样
// -------- start
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;
}
}
}
共享锁获取
当前state状态是独占锁
线程获取共享锁, 加入到锁同步队列
FIFO的同步队列
加入同步队列是, head->trail
共享1, 共享2, 共享3, 独占1, 共享4, 独占2, 共享5
则只能先唤起 共享1, 共享2, 共享3,
当 独占1释放了独占锁之后, 唤起 共享4,
当共享4释放了共享锁之后, 唤起 独占2
独占2释放独占锁之后, 唤起 共享5
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) // 当前线程获取共享锁失败
doAcquireShared(arg); // 加入到同步队列
}
// 加入到同步队列的操作
private void doAcquireShared(int arg) {
// 加入到锁同步队列
final Node node = addWaiter(Node.SHARED);
// 执行获取共享锁和线程挂起的逻辑
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg); // 如果当前节点的前驱节点是head节点,则尝试获取共享锁。
if (r >= 0) { // 获取共享锁成功, 把并把head节点替换成当前节点。
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
// 执行线程挂起
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
加入到锁同步队列
private Node addWaiter(Node mode) {
// 将节点加入锁同步队列
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// 自旋, 将节点加入到锁同步队列
enq(node);
return node;
}
// 自旋, 将节点加入到锁同步队列
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
将head节点替换成当前节点,
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node); // 把head替换成当前节点。
// propagate > 0 表示当前节点获取共享锁成功
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next; // 当前节点的后续的节点
if (s == null || s.isShared()) // 如果后续节点也是共享锁节点, 则
doReleaseShared();
}
}
private void doReleaseShared() {
for (;;) {
Node h = head; // 头节点
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) { // 表明h节点曾经被挂起过
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) // 自旋
continue; // loop to recheck cases
unparkSuccessor(h); // h节点waitStatus改成0成功后, 唤起后继节点
}
// h节点的waitStatus已经是0, 且h节点的statusWait设置位Propagate失败, 则自旋
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
//
if (h == head) // loop if head changed
break;
}
}
unparkSuccessor唤起后继节点
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next; // head节点后继节点
if (s == null || s.waitStatus > 0) { // 移除waitStatus为cancelled的节点。
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread); // 唤醒后继节点, 后继节点在doAcquireShared方法中醒来; 并执行tryAcquireShared获取共享锁
}
共享锁释放锁
- 只有共享锁线程全部都释放了, 才有必要唤起独占锁线程
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
if (firstReader == current) { // 如果是firstReader线程
// assert firstReaderHoldCount > 0;
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--; // 头一个的线程获取共享锁的次数加1
} else { // 非头一个的其他线程
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
int count = rh.count;
if (count <= 1) {
readHolds.remove(); //直接从ThreadLocal删除线程
if (count <= 0)
throw unmatchedUnlockException();
}
--rh.count; // 非头一个的当前线程获取共享锁的次数减1
}
// state高16位减1
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT; // state高16位减1
if (compareAndSetState(c, nextc))
return nextc == 0; // true, 共享锁全部释放; false, 共享锁正在被当前或者其他线程占用
}
}