package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.LockSupport;
public class StampedLock implements java.io.Serializable {
private static final long serialVersionUID = -6001602636862214147L;
/** Number of processors, for spin control */
private static final int NCPU = Runtime.getRuntime().availableProcessors();
/** Maximum number of retries before enqueuing on acquisition */
//单cpu不自旋
private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
/** Maximum number of retries before blocking at head on acquisition */
private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
/** Maximum number of retries before re-blocking */
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
/** The period for yielding when waiting for overflow spinlock */
private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
//读占低7位
private static final int LG_READERS = 7;
// Values for lock state and stamp operations
private static final long RUNIT = 1L;
// 1000 0000高第8位是1代表有写锁
private static final long WBIT = 1L << LG_READERS;
// 0111 1111低7位代表读线程数
private static final long RBITS = WBIT - 1L;
// 1111 1111
private static final long ABITS = RBITS | WBIT;
// 0111 1110
private static final long RFULL = RBITS - 1L;
//1..1000 0000从高8位起全是1
//用于提取8-64位代表的版本号
//注:读锁不会导致版本号发生变化,只有写锁才会
//因此判断一个stamp与当前state的版本是否一致(期间没有线程持有过写锁)
//使用:(state & SBITS) == (stamp & SBITS)
private static final long SBITS = ~RBITS; // note overlap with ABITS
//1 0000 0000
private static final long ORIGIN = WBIT << 1;
private static final long INTERRUPTED = 1L;
// Values for node status; order matters
private static final int WAITING = -1;
private static final int CANCELLED = 1;
// Modes for nodes (int not boolean to allow arithmetic)
private static final int RMODE = 0;
private static final int WMODE = 1;
/** Wait nodes */
static final class WNode {
volatile WNode prev;//指向前一个节点
volatile WNode next;//指向下一个节点
volatile WNode cowait; //相邻的读线程作为一组使用cowait来维护单链
volatile Thread thread; //等待的线程
volatile int status; // 0, WAITING, or CANCELLED
final int mode; // RMODE or WMODE
WNode(int m, WNode p) { mode = m; prev = p; }
}
/** Head of CLH queue */
private transient volatile WNode whead;//虚拟头节点
/** Tail (last) of CLH queue */
private transient volatile WNode wtail;//指向尾节点
//返回一个读锁视图,类似ReentrantReadWriteLock.readerLock()
transient ReadLockView readLockView;
//返回一个写锁视图,类似ReentrantReadWriteLock.writeLock()
transient WriteLockView writeLockView;
//以上两个的快捷方式:可以返回读或写视图
transient ReadWriteLockView readWriteLockView;
//状态值
//低7位保存写锁个数,第8位保存是否为写锁, 8-64位为版本号
private transient volatile long state;
//低7位保存写锁个数默认最大存储为126(111 1110)个,
//如果读锁个数超过126,将超过的个数保存到readerOverflow中
private transient int readerOverflow;
public StampedLock() {
state = ORIGIN;//初始状态1 0000 0000
}
//获取一个写锁,成功返回一个标记,失败则等待
public long writeLock() {
long s, next; // bypass acquireWrite in fully unlocked case only
//还没有锁则设置为写锁,否则调用acquireWrite自旋获取锁
return ((((s = state) & ABITS) == 0L &&
U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
next : acquireWrite(false, 0L));
}
//尝试获取锁,成功返回stamp值否则返回0
public long tryWriteLock() {
long s, next;
return ((((s = state) & ABITS) == 0L &&//还没有锁则设置为写锁,否则返回失败0
U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
next : 0L);
}
//尝试获取锁并指定超时时间,成功返回stamp值否则返回0
public long tryWriteLock(long time, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(time);
//没有被中断,否则抛InterruptedException退出
if (!Thread.interrupted()) {
long next, deadline;
//等待前先尝试获取锁,成功返回,失败下面进行等待
if ((next = tryWriteLock()) != 0L)
return next;
if (nanos <= 0L)
return 0L;
//我理解的是相加可能会溢出小于0,等于0什么情况?
if ((deadline = System.nanoTime() + nanos) == 0L)
deadline = 1L;
//调用acquireWrite获取锁(内部先自旋,再等待)
//acquireWrite返回0说明超时
if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
return next;
}
throw new InterruptedException();
}
//获取一个写锁,成功返回一个标记,失败则等待,可响应中断
public long writeLockInterruptibly() throws InterruptedException {
long next;
if (!Thread.interrupted() &&
(next = acquireWrite(true, 0L)) != INTERRUPTED)
return next;
throw new InterruptedException();
}
//获取一个悲观(所谓悲观就是会锁定)读锁,成功返回一个标记,失败则等待
public long readLock() {
long s = state, next; // bypass acquireRead on common uncontended case
//RFULL为低7位1111110
return ((whead == wtail && (s & ABITS) < RFULL &&
U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
//如果头尾不相等说明有线程在排队等待或者有人持有写锁那么调用acquireRead自旋获取锁
next : acquireRead(false, 0L));
}
//尝试获取一个悲观读锁,成功返回一个标记,失败返回0
public long tryReadLock() {
for (;;) {
long s, m, next;
if ((m = (s = state) & ABITS) == WBIT)
return 0L;//已有线程持有写锁,返回0
else if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
return next;
}
else if ((next = tryIncReaderOverflow(s)) != 0L)
return next;//一旦读锁个数超过126,那么所有读线程返回的stamp会一样
}
}
//指定时间内尝试获取一个悲观读锁,成功返回一个标记,失败返回0
public long tryReadLock(long time, TimeUnit unit)
throws InterruptedException {
long s, m, next, deadline;
long nanos = unit.toNanos(time);
if (!Thread.interrupted()) {
if ((m = (s = state) & ABITS) != WBIT) {
if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
return next;
}
else if ((next = tryIncReaderOverflow(s)) != 0L)
return next;
}
if (nanos <= 0L)
return 0L;
if ((deadline = System.nanoTime() + nanos) == 0L)
deadline = 1L;
if ((next = acquireRead(true, deadline)) != INTERRUPTED)
return next;
}
throw new InterruptedException();
}
//获取一个悲观读锁,成功返回一个标记,否则等待,可响应中断
public long readLockInterruptibly() throws InterruptedException {
long next;
if (!Thread.interrupted() &&
(next = acquireRead(true, 0L)) != INTERRUPTED)
return next;
throw new InterruptedException();
}
//获取一个版本号,此方法并不会加锁(设置锁标识)
//用于检测在tryOptimisticRead与validate是否有线程获取了写锁
//只有当前未在写入模式时才返回非0
public long tryOptimisticRead() {
long s;
//如果高第8位是1说明有写锁,那么返回0,否则返回第8-64位的值(版本号)
return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
}
//验证从调用tryOptimisticRead开始到validate这段时间内有没有线程持有过写锁,
//有返回false. 注:stamp为0也返回false
//如果期间有写锁但调用validate时已经释放了会怎样?
//当然也返回false,因为释放写锁后版本号会递增的
public boolean validate(long stamp) {
U.loadFence();
//不关心低七位
return (stamp & SBITS) == (state & SBITS);
}
//释放写锁
public void unlockWrite(long stamp) {
WNode h;
//写锁是独占锁因此必须保证stamp等于state
//状态值不对抛异常
if (state != stamp || (stamp & WBIT) == 0L)
throw new IllegalMonitorStateException();
//通过加法将第8位清零,为什么用加法而不是直接将第8位设置为0?
//使用加法具有抗否认性,8-64位代表的版本号会变化
//因此在tryOptimisticRead与validate之间获取并释放了写锁
//也能被检测到
state = (stamp += WBIT) == 0L ? ORIGIN : stamp;
if ((h = whead) != null && h.status != 0)
//唤醒队列线程
release(h);
}
//释放一个读锁
public void unlockRead(long stamp) {
long s, m; WNode h;
for (;;) {
//版本号必须一致(8-64位)
if (((s = state) & SBITS) != (stamp & SBITS) ||
//不可以unlock一个stamp为0的标记
//当前state已经清零(或存在写锁抛异常
(stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
throw new IllegalMonitorStateException();
if (m < RFULL) {
//将读锁个数递减1
if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
//如果当前释放的是最后一个读锁,且有线程在等待锁那么唤醒一个线程
if (m == RUNIT && (h = whead) != null && h.status != 0)
release(h);
break;
}
}
//读锁个数超过126,从readerOverflow中递减
else if (tryDecReaderOverflow(s) != 0L)
break;
}
}
public void unlock(long stamp) {
long a = stamp & ABITS, m, s; WNode h;
//state与stamp必须版本号一致
while (((s = state) & SBITS) == (stamp & SBITS)) {
if ((m = s & ABITS) == 0L)//不包含任何锁,抛异常
break;
//1.当前state是写模式,那么m与a必须相等(写是独占锁,其它线程不可能再修改state)
else if (m == WBIT) {
if (a != m)
break;
state = (s += WBIT) == 0L ? ORIGIN : s;
if ((h = whead) != null && h.status != 0)
release(h);//头结点状态非0说明队列有线程等待锁,那么唤醒一个线程
return;
}
//2.当前state是读模式,那么stamp也必须是读模式否则退出循环
else if (a == 0L || a >= WBIT)
break;
else if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
//如果释放的是最后一个读锁且等待队列有线程等待那么唤醒后续线程
if (m == RUNIT && (h = whead) != null && h.status != 0)
release(h);
return;
}
}
else if (tryDecReaderOverflow(s) != 0L)
return;
}
throw new IllegalMonitorStateException();
}
//读锁尝试转化为写锁,仅当其他线程没有持有读锁才能转化成功
//有效返回:
//1.当前没有持有任何锁,转换为写锁
//2.当前锁已经是写锁模式直接返回stamp
//3.当前锁处于读锁模式,并且没有其他线程是读锁模式
//4.其它失败,返回0
public long tryConvertToWriteLock(long stamp) {
long a = stamp & ABITS, m, s, next;
//stamp与state版本匹配
while (((s = state) & SBITS) == (stamp & SBITS)) {
if ((m = s & ABITS) == 0L) {//当state低8位是0,stamp必须一样,否则失败
if (a != 0L)
break;
if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
return next;
}
//当前stamp是写模式直接返回stamp(无需转换)
else if (m == WBIT) {
if (a != m)//a与m不等必定是状态不对
break;
//当前已经是写模式了无需转换
return stamp;
}
//必须仅有一个读锁才能转(不允许其它线程持有读)
else if (m == RUNIT && a != 0L) {
if (U.compareAndSwapLong(this, STATE, s,//释放读,切入写
next = s - RUNIT + WBIT))
return next;
}
else
break;
}
return 0L;
}
//获取了写锁将其转换为读锁
//有效返回:
//1.当前没有持有任何锁,转换为读锁
//2.当前锁已经是读模式直接返回stamp
//3.当前锁处于写模式,那么释放写锁并申请读锁
//4.其它失败,返回0
public long tryConvertToReadLock(long stamp) {
long a = stamp & ABITS, m, s, next; WNode h;
//stamp与state版本匹配
while (((s = state) & SBITS) == (stamp & SBITS)) {
//没有持有任何锁,转换为读锁
if ((m = s & ABITS) == 0L) {
if (a != 0L)//当state低8位是0,stamp必须一样,否则失败
break;
else if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
return next;
}
else if ((next = tryIncReaderOverflow(s)) != 0L)
return next;
}
else if (m == WBIT) {
if (a != m)
break;
state = next = s + (WBIT + RUNIT);//取消写锁累加读锁
if ((h = whead) != null && h.status != 0)
release(h);//既然没有写锁那么读线程应该释放
return next;
}
else if (a != 0L && a < WBIT)
return stamp;//已经是读模式,无需转
else
break;
}
return 0L;
}
//此方法等价于释放锁+tryOptimisticRead(返回版本号8-64位)
//1.如果当前线程持有写锁相当于先释放写锁,再调用tryOptimisticRead
//2.如果当前线程持有读锁相当于先释放读锁,再调用tryOptimisticRead
public long tryConvertToOptimisticRead(long stamp) {
long a = stamp & ABITS, m, s, next; WNode h;
//禁止tryConvertToOptimisticRead与validate之间的重排序
U.loadFence();
for (;;) {
//stamp与state版本匹配
if (((s = state) & SBITS) != (stamp & SBITS))
break;
if ((m = s & ABITS) == 0L) {
if (a != 0L)
break;
return s;
}
else if (m == WBIT) {
if (a != m)
break;
//当前线程持有写锁,先释放再返回版本
state = next = (s += WBIT) == 0L ? ORIGIN : s;
if ((h = whead) != null && h.status != 0)
release(h);
return next;
}
else if (a == 0L || a >= WBIT)
break;
//当前stamp是读模式
else if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {//释放读锁
if (m == RUNIT && (h = whead) != null && h.status != 0)
release(h);
return next & SBITS;
}
}
else if ((next = tryDecReaderOverflow(s)) != 0L)
return next & SBITS;
}
return 0L;
}
//尝试释放锁,仅当为写模式才能释放,其它模式返回false
public boolean tryUnlockWrite() {
long s; WNode h;
if (((s = state) & WBIT) != 0L) {
state = (s += WBIT) == 0L ? ORIGIN : s;
if ((h = whead) != null && h.status != 0)
release(h);
return true;
}
return false;
}
//尝试释放一个读锁,仅当非写入模式才可能返回true
public boolean tryUnlockRead() {
long s, m; WNode h;
while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
if (m == RUNIT && (h = whead) != null && h.status != 0)
release(h);
return true;
}
}
else if (tryDecReaderOverflow(s) != 0L)
return true;
}
return false;
}
//根据指定的标识返回标识指示的读锁个数
private int getReadLockCount(long s) {
long readers;
if ((readers = s & RBITS) >= RFULL)
readers = RFULL + readerOverflow;
return (int) readers;
}
public boolean isWriteLocked() {
return (state & WBIT) != 0L;
}
public boolean isReadLocked() {
return (state & RBITS) != 0L;
}
//返回当前读锁个数
public int getReadLockCount() {
return getReadLockCount(state);
}
public String toString() {
long s = state;
return super.toString() +
((s & ABITS) == 0L ? "[Unlocked]" :
(s & WBIT) != 0L ? "[Write-locked]" :
"[Read-locks:" + getReadLockCount(s) + "]");
}
//返回一个读锁的视图
public Lock asReadLock() {
ReadLockView v;
return ((v = readLockView) != null ? v :
(readLockView = new ReadLockView()));
}
//返回一个写锁的视图
public Lock asWriteLock() {
WriteLockView v;
return ((v = writeLockView) != null ? v :
(writeLockView = new WriteLockView()));
}
public ReadWriteLock asReadWriteLock() {
ReadWriteLockView v;
return ((v = readWriteLockView) != null ? v :
(readWriteLockView = new ReadWriteLockView()));
}
// view classes
//实现Lock的语义但不支持newCondition方法(newCondition基于AQS)
final class ReadLockView implements Lock {
public void lock() { readLock(); }//舍弃原因方法的返回值stamp
public void lockInterruptibly() throws InterruptedException {
readLockInterruptibly();
}
public boolean tryLock() { return tryReadLock() != 0L; }
public boolean tryLock(long time, TimeUnit unit)
throws InterruptedException {
return tryReadLock(time, unit) != 0L;
}
public void unlock() { unstampedUnlockRead(); }
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
final class WriteLockView implements Lock {
public void lock() { writeLock(); }
public void lockInterruptibly() throws InterruptedException {
writeLockInterruptibly();
}
public boolean tryLock() { return tryWriteLock() != 0L; }
public boolean tryLock(long time, TimeUnit unit)
throws InterruptedException {
return tryWriteLock(time, unit) != 0L;
}
public void unlock() { unstampedUnlockWrite(); }
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
final class ReadWriteLockView implements ReadWriteLock {
public Lock readLock() { return asReadLock(); }
public Lock writeLock() { return asWriteLock(); }
}
// Unlock methods without stamp argument checks for view classes.
// Needed because view-class lock methods throw away stamps.
//释放一个写锁,不用传入或返回stamp
final void unstampedUnlockWrite() {
WNode h; long s;
if (((s = state) & WBIT) == 0L)
throw new IllegalMonitorStateException();
state = (s += WBIT) == 0L ? ORIGIN : s;
if ((h = whead) != null && h.status != 0)//status为0说明后面没有线程等待锁
release(h);
}
//释放一个读锁,不用传入或返回stamp
final void unstampedUnlockRead() {
for (;;) {
long s, m; WNode h;
if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
throw new IllegalMonitorStateException();
else if (m < RFULL) {
if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
if (m == RUNIT && (h = whead) != null && h.status != 0)
release(h);
break;
}
}
else if (tryDecReaderOverflow(s) != 0L)
break;
}
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
state = ORIGIN; // reset to unlocked state
}
//当读锁个数超过126是将超出数保存到readerOverflow
//此方法必须置于上层调用的自旋块中,因为必须在此返回0(失败)后重试
private long tryIncReaderOverflow(long s) {//s为state的拷贝
// assert (s & ABITS) >= RFULL;
if ((s & ABITS) == RFULL) {
//如果低7个位保存数等于126:1111110
//那么将读锁增量累加到readerOverflow中
//因此如果低7个位的值是126那么总的读锁个数是:126+readerOverflow
//递增前将低7位临时全部设为1,以躲避并发
if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
++readerOverflow;
//if中会将state的低7位变成127:111 1111
//在进入这行语句将state还原成:111 1110前其他线程调用会返回0
//这样的话会导致问题,因此上层调用如tryReadLock遇到返回0的情况会
//继续重试,直到非0
state = s;
return s;
}
}
//低7位是127返回0,调用者发现返回0继续重试调用
else if ((LockSupport.nextSecondarySeed() &
OVERFLOW_YIELD_RATE) == 0)
Thread.yield();//让其它线程先执行以便更新state后再回来重试
return 0L;
}
//当读锁个数超过126时递减读锁要调用的方法
private long tryDecReaderOverflow(long s) {
// assert (s & ABITS) >= RFULL;
if ((s & ABITS) == RFULL) {
//递减前将低7位都设成1,以躲避并发
if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
int r; long next;
if ((r = readerOverflow) > 0) {
readerOverflow = r - 1;
next = s;
}
else
next = s - RUNIT;
//在将state设为next之前其它线程不会进入到这个if分支
state = next;
return next;
}
}
else if ((LockSupport.nextSecondarySeed() &
OVERFLOW_YIELD_RATE) == 0)
Thread.yield();
return 0L;
}
//释放队列开头的一个线程
private void release(WNode h) {
if (h != null) {
WNode q; Thread w;
//将头结点由WAITING设置为0,以免重复操作
U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
//下一个节点被删除了,需要重新找到队列开头的有效节点
if ((q = h.next) == null || q.status == CANCELLED) {
for (WNode t = wtail; t != null && t != h; t = t.prev)
//从尾节点向前遍历直到遇到头节点为止
if (t.status <= 0)
q = t;
}
if (q != null && (w = q.thread) != null)
//唤醒节点
U.unpark(w);
}
}
private long acquireWrite(boolean interruptible, long deadline) {
WNode node = null, p;
//到银行办业务
//第一个for:好像没几个人,说不定要轮到我了,不取号了,
//四周转转先(自旋,运气好自旋过程中其它线程释放了锁)
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
//如果有:算了不用自旋了,还是老老实实的排队等待吧准备退出第一个for
spins = (m == WBIT && wtail == whead) ? SPINS : 0;
else if (spins > 0) {
//自旋等待,不能空旋,做一些虚拟运算以防cpu"累死"
if (LockSupport.nextSecondarySeed() >= 0)
--spins;
}
//我都达到最大自旋次数了,还是没获取到锁,算了准备排队等待吧,
//咦,排号的窗口怎么没人?(队列还没初始化),唉!“伙计”睡醒没?上班了!
else if ((p = wtail) == null) { // initialize queue
WNode hd = new WNode(WMODE, null);//虚拟头结点
if (U.compareAndSwapObject(this, WHEAD, null, hd))
wtail = hd;
}
//队列已经初始化好了,叫个“号”吧,p这个人在我前面啊
else if (node == null)
node = new WNode(WMODE, p);
//咦,什么情况,前面的人放弃了(取消)?
//我得记下,排在我前面的是现在的p,一会还得找“伙计”重新排下,我在现在的p的后面了
else if (node.prev != p)
node.prev = p;
//“伙计”睡醒没,麻烦帮我排个号,我在p的后面
else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
p.next = node;
break;
}
}
//第二个for循环
//号排好了,我是不是得找个地方坐着等呢?(思考中)
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
}
//更新前节点的状态为WAITING,准备坐着等(挂起)
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 {
//前节点状态已更新为WAITING,准备挂起当前线程
long time; // 0 argument to park means no timeout
if (deadline == 0L)//0代表无超时
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, node, false);//false代表非中断取消
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
//前节点的状态是WAITING并且(当前线程不是排在第一位,或排在第一位但其它线程持有锁)
//那么需要挂起当前线程
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);
//interruptible指示是否需要响应中断
//被唤醒后需要检查是否被中断,这行代码有bug容易导致死循环
//正确写法应该是:Thread.interrupted() && interruptible
if (interruptible && Thread.interrupted())
return cancelWaiter(node, node, true);
}
}
}
}
private long acquireRead(boolean interruptible, long deadline) {
WNode node = null, p;
for (int spins = -1;;) {
WNode h;
//队列未初始化或队列是空,说明我是第一个排队的,自旋一会试试
if ((h = whead) == (p = wtail)) {
for (long m, s, ns;;) {
if ((m = (s = state) & ABITS) < RFULL ?//唯有线程持有写锁,那么可以获取读锁
U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
(m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))//读锁数量超过126
return ns;//返回标识
else if (m >= WBIT) {//有线程持有写锁,初始化自旋数或自旋等
if (spins > 0) {
//防止空旋
if (LockSupport.nextSecondarySeed() >= 0)
--spins;
}
else {
if (spins == 0) {//已完成指定数量的自旋该退出自旋了,有必要进入等待(挂起)
WNode nh = whead, np = wtail;
//这行代码的目的是当spins为0是需要跳出循环
//nh == h && np == p判断头尾是否变化过,没有化直接break
//如果有变化重新更新h和p使其指向头尾此时头尾相同又会开启新一轮自旋
if ((nh == h && np == p) || (h = nh) != (p = np))
break;
}
//初始化自旋数
spins = SPINS;
}
}
}
}//自旋结束或无需自旋,有必要挂起线程,创建node入队吧
//p前一个节点为null,队列未初始化
if (p == null) { // initialize queue
WNode hd = new WNode(WMODE, null);//初始化队列,新增虚拟头结点
if (U.compareAndSwapObject(this, WHEAD, null, hd))
wtail = hd;
}
//创建一个等待节点(读模式)准备插入到队列中
else if (node == null)
node = new WNode(RMODE, p);
//前一个节点是头结点或前一个节点是写模式那么当前节点入等待队列
//如果前一个节点也是读模式那么当前节点会加入到前一个节点的cowait指针维护的
//链中,这样做的目的当一个读线程获取了锁那么此线程的cowait链中的所有读线程
//都能获取锁
else if (h == p || p.mode != RMODE) {
if (node.prev != p)//不等说明前节点被取消,重新更新prev引用
node.prev = p;
else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
p.next = node;
break;//节点插入队列成功跳出第一个循环,进入第二段for循环
}
}
//前一个节点是读模式那么将当前节点加入到前一个节点的cowait链中
//cowait链中的节点的pre引用总是指向此链中的第一个读模式的节点(group)
//W:写模式,R:读模式,n队列的next指针,cw:cowait链的cowait指针
//有线程获取写锁,此时node2,node3,node4,node5依次请求读锁,此时队列结构如下:
//node2在等待队列中,而node5,node4,node3在cowait链中
// head tail
// | |
// |<------prev----|
//dummy(W)----n---->node2(R)
// | /|\ /|\ /|\_________
// | | \ \
// cw | prev prev
// | | \ \
// \|/ | \ \
// node5---cw---node4---cw---node3---cw---null
else if (!U.compareAndSwapObject(p, WCOWAIT,
node.cowait = p.cowait, node))
node.cowait = null;//比较失败没关系,会继续自旋重试
else {
for (;;) {
WNode pp, c; Thread w;
//助推:释放开头的读线程(此节点会变成虚拟头结点),这里帮助其释放cowait链
if ((h = whead) != null && (c = h.cowait) != null &&
U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
(w = c.thread) != null) // help release
U.unpark(w);
//p为读模式组中第一个节点(cowait链的第一个节点)
//cowait中的node的prev都指向p
//if条件的意思是读模式这一组节点处在队列开头位置
//那么此时如果还没有线程获取写锁,是可以获取读锁的
if (h == (pp = p.prev) || h == p || pp == null) {
long m, s, ns;
do {
if ((m = (s = state) & ABITS) < RFULL ?
U.compareAndSwapLong(this, STATE, s,
ns = s + RUNIT) :
(m < WBIT &&
(ns = tryIncReaderOverflow(s)) != 0L))
return ns;
} while (m < WBIT);
}
//尝试挂起线程
if (whead == h && p.prev == pp) {
long time;
//pp == null代表p就是头节点
//h == p
//p.status > 0 cowait第一个节点被取消
if (pp == null || h == p || p.status > 0) {
//将node设为null并退出当前循环,进入外层循环以重新自旋或new
//一个节点并插入队列
//当p被取消,只要p还没来得及从队列删除,那么会死循环执行相同操作直到p被移除
node = null; // throw away
break;
}
//准备挂起线程
if (deadline == 0L)
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, p, false);
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
if ((h != pp || (state & ABITS) == WBIT) &&
whead == h && p.prev == pp)
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
//这里会导致死循环,比如一个读线程在等待,因调用了interupt被唤醒
//如果interruptible是false那么中断标识不会被清除再次自旋调用park方法不会挂起导致一直死循环
//https://bugs.openjdk.java.net/browse/JDK-8049843
if (interruptible && Thread.interrupted())
return cancelWaiter(node, p, true);
}
}
}
}//第一段for结束
//第二段for循环
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 m, s, ns;
if ((m = (s = state) & ABITS) < RFULL ?
U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
(m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
WNode c; Thread w;
whead = node;
node.prev = null;
//当一个读线程被唤醒后,紧跟其后的所有同等地位的读线程会一起被
//唤醒,这些线程保存在cowait的链中
while ((c = node.cowait) != null) {
if (U.compareAndSwapObject(node, WCOWAIT,
c, c.cowait) &&
(w = c.thread) != null)
U.unpark(w);
}
return ns;
}
else if (m >= WBIT &&
LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
break;
}
}
else if (h != null) {
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) {
//旧的前节点被取消重新更新prev与next引用
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;
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) == WBIT) &&
whead == h && node.prev == p)
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
//注这里与上面的cancelWaiter(node, p, true);不同
//调用参数是node,node说明要删除的节点就是cowait链的头节点
return cancelWaiter(node, node, true);
}
}
}
}
//取消一个节点(调用了中断方法interrupted为true,获取锁超时interrupted为false)
//group为node的prev引用,也就是cowait链的第一个节点
private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
if (node != null && group != null) {
Thread w;
node.status = CANCELLED;//设置取消节点的状态值为1
// unsplice cancelled nodes from group
//遍历group的cowait链,删除上一行取消的节点
//如果删除的节点是cowait链的头节点,也就是group本身
//for循环不会删除group
for (WNode p = group, q; (q = p.cowait) != null;) {
if (q.status == CANCELLED) {
U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
//成功找到一个并删除,那么重新遍历一次
p = group; // restart
}
else
p = q;
}
//如果要删除的节点就是cowait链的头结点
if (group == node) {
//第一个循环:唤醒cowait链中的所有线程,以便它们重新更新头结点
for (WNode r = group.cowait; r != null; r = r.cowait) {
if ((w = r.thread) != null)
U.unpark(w); // wake up uncancelled co-waiters
}
for (WNode pred = node.prev; pred != null; ) { // unsplice
WNode succ, pp; // find valid successor
//node要删除,先找到其后的第一个有效后继
//
while ((succ = node.next) == null ||
succ.status == CANCELLED) {
WNode q = null; // find successor the slow way
//从尾反向查找到最后一个非删除的节点便是node后面的第一个有效后继
for (WNode t = wtail; t != null && t != node; t = t.prev)
if (t.status != CANCELLED)
q = t; // don't link if succ cancelled
if (succ == q || // ensure accurate successor
U.compareAndSwapObject(node, WNEXT,//将node的next设为其后第一个未删除的节点
succ, succ = q)) {
//node本身就是尾节点那么将tail设为其前一个节点
if (succ == null && node == wtail)
U.compareAndSwapObject(this, WTAIL, node, pred);
break;
}
}
if (pred.next == node) // unsplice pred link
//节点删除
U.compareAndSwapObject(pred, WNEXT, node, succ);
if (succ != null && (w = succ.thread) != null) {
//唤醒node的后继节点的线程以便其重新更新prev节点
succ.thread = null;
U.unpark(w); // wake up succ to observe new pred
}
if (pred.status != CANCELLED || (pp = pred.prev) == null)
break;
//如果pre节点也被删除那么更新node.pre为pp
node.prev = pp; // repeat if new pred wrong/cancelled
U.compareAndSwapObject(pp, WNEXT, pred, succ);
pred = pp;
}
}
}
WNode h; // Possibly release first waiter
while ((h = whead) != null) {
long s; WNode q; // similar to release() but check eligibility
if ((q = h.next) == null || q.status == CANCELLED) {
for (WNode t = wtail; t != null && t != h; t = t.prev)
if (t.status <= 0)
q = t;
}//q为头节点之后第一个未取消的节点
if (h == whead) {
//这里的意思是:队列中有等待的节点,且(要么没有线程持有锁要么有且仅有读锁)
//那么可以唤醒一个线程
if (q != null && h.status == 0 &&
((s = state) & ABITS) != WBIT && // waiter is eligible
(s == 0L || q.mode == RMODE))
release(h);
//退出循环
break;
}
}
return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
}
// Unsafe mechanics
private static final sun.misc.Unsafe U;
private static final long STATE;
private static final long WHEAD;
private static final long WTAIL;
private static final long WNEXT;
private static final long WSTATUS;
private static final long WCOWAIT;
private static final long PARKBLOCKER;
static {
try {
U = sun.misc.Unsafe.getUnsafe();
Class<?> k = StampedLock.class;
Class<?> wk = WNode.class;
STATE = U.objectFieldOffset
(k.getDeclaredField("state"));
WHEAD = U.objectFieldOffset
(k.getDeclaredField("whead"));
WTAIL = U.objectFieldOffset
(k.getDeclaredField("wtail"));
WSTATUS = U.objectFieldOffset
(wk.getDeclaredField("status"));
WNEXT = U.objectFieldOffset
(wk.getDeclaredField("next"));
WCOWAIT = U.objectFieldOffset
(wk.getDeclaredField("cowait"));
Class<?> tk = Thread.class;
PARKBLOCKER = U.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
} catch (Exception e) {
throw new Error(e);
}
}
}