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, 共享锁正在被当前或者其他线程占用
}
}