共计 2620 个字符,预计需要花费 7 分钟才能阅读完成。
StampedLock
最近看并发工具类的遇到这个玩意,据说效率比 ReentrantLock 高,咱也没用过,闲得慌,源码先扒了再说,不定期更新。
锁状态变量
既然是相似读写锁,必定也有变量用于记录锁状态,绝对于读写锁应用 Int,StampedLock
中使 Long 类型(64 位)示意锁状态,其中第 8 位示意写锁持有状态,低 7 位用于示意持有读锁的线程数。(目前还未搞懂为啥用 Long,待前面钻研)
private static final long RUNIT = 1L; // 读锁线程减少时,// 获取写锁状态的掩码:1000 000
private static final long WBIT = 1L << LG_READERS;
// 获取读锁状态的掩码:0111 1111
private static final long RBITS = WBIT - 1L;
// 读锁持有数量的下限
private static final long RFULL = RBITS - 1L;
// 获取锁的状态,用于判断是否有线程持有读锁或写锁
private static final long ABITS = RBITS | WBIT;
//RBITS 取反,作用未钻研
private static final long SBITS = ~RBITS; // note overlap with ABITS
写锁获取
public long writeLock() {
long s, next;
// 如果没有任何线程持有锁,CAS 尝试增加写锁状态
// 如果失败,则 acquireWrite 办法中自旋尝试获锁,再次失败入队
return ((((s = state) & ABITS) == 0L &&
U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
next : acquireWrite(false, 0L));
}
acquireWrite
办法巨长,真难看
private long acquireWrite(boolean interruptible, long deadline) {
WNode node = null, p;
for (int spins = -1;;) { // spin while enqueuing
long m, s, ns;
// 再次尝试获取写锁,胜利则返回以后的锁状态
if ((m = (s = state) & ABITS) == 0L) {if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
return ns;
}
else if (spins < 0)
// 写锁被其它线程占有,且期待队列为空(头等于尾)时,不批改 spins
spins = (m == WBIT && wtail == whead) ? SPINS : 0;
else if (spins > 0) {
// 产生一个随机数,判断是否大于 0
if (LockSupport.nextSecondarySeed() >= 0)
--spins;
}
else if ((p = wtail) == null) { // 初始化期待队列
WNode hd = new WNode(WMODE, null);
if (U.compareAndSwapObject(this, WHEAD, null, hd))
wtail = hd;
}
// 上面三个 if 就是将 node 采纳尾插法插入期待队列
else if (node == null)
node = new WNode(WMODE, p);
else if (node.prev != p)
node.prev = p;
else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
p.next = node;
break;
}
}
for (int spins = -1;;) {
WNode h, np, pp; int ps;
if ((h = whead) == p) {if (spins < 0)
spins = HEAD_SPINS;
else if (spins < MAX_HEAD_SPINS)
spins <<= 1;
for (int k = spins;;) { // spin at head
long s, ns;
if (((s = state) & ABITS) == 0L) {
if (U.compareAndSwapLong(this, STATE, s,
ns = s + WBIT)) {
whead = node;
node.prev = null;
return ns;
}
}
else if (LockSupport.nextSecondarySeed() >= 0 &&
--k <= 0)
break;
}
}
else if (h != null) { // help release stale waiters
WNode c; Thread w;
while ((c = h.cowait) != null) {if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
(w = c.thread) != null)
U.unpark(w);
}
}
if (whead == h) {if ((np = node.prev) != p) {if (np != null)
(p = np).next = node; // stale
}
else if ((ps = p.status) == 0)
U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
else if (ps == CANCELLED) {if ((pp = p.prev) != null) {
node.prev = pp;
pp.next = node;
}
}
else {
long time; // 0 argument to park means no timeout
if (deadline == 0L)
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, node, false);
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
whead == h && node.prev == p)
U.park(false, time); // emulate LockSupport.park
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
return cancelWaiter(node, node, true);
}
}
}
}
正文完