package com.haogrgr.test.juc;
import java.util.concurrent.locks.AbstractOwnableSynchronizer;
import java.util.concurrent.locks.LockSupport;
import sun.misc.Unsafe;
@SuppressWarnings("restriction")
public class MyAqs extends AbstractOwnableSynchronizer {
private static final long serialVersionUID = 1L;
static final long spinForTimeoutThreshold = 1000L;
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
//将节点加入到链表尾部
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
//tail为空, 补上tail/head, 进入下次循环, 将node设置为新的tail
//因为acquire时, 如果直接tryacquire成功了, 则不会加入链表, 所以这里补上.
if (compareAndSetHead(new Node())) {
tail = head;
}
}
else {
//1.设置node.prev, 2.cas设置node为tail, 3.成功, 再设置t.next
//所以, 入队成功(2操作完), 则prev一定被设置, 但是可能3还没有执行, 所以prev.next可能为null
//所以, 后面可以看到有些地方并不是.next遍历下去, 而是.prev遍历下去, 防止漏掉已入队的节点
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
//添加指定模式(mode)的等待节点到链表尾部
private Node addWaiter(Node mode) {
//待添加的节点, mode为独占(EXCLUSIVE)or共享(SHARED), 初始状态为0.
Node node = new Node(Thread.currentThread(), mode);
//与enq逻辑类似, 链表不为空时, cas设置tail, 失败再走enq
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//enq就多了个判断tail为空是, new已个Node放进去, 然后在吧node加入链表
enq(node);
return node;
}
//唤醒node后继的有效节点, 被cancelAcquire, doReleaseShared, release方法调用.
private void unparkSuccessor(Node node) {
//走cancelAcquire来到这里的话, 就不改状态为0, 因为一旦node进入到cancel就不会进入其他状态了
//为0状态的话, 就不需要修改状态了, 设置为0状态, 是为了表示, 走到这里已经要unpark后续节点了, 清除signel状态
//这里修改失败, 不需要管, 什么时候会失败, cancelAcquire不会修改, release时, 状态为0不需要修改, 状态为Signal, 后面的线程也不会修改head状态
//所以这里只有doReleaseShared时, 可能出现修改失败的情况, TODO
int ws = node.waitStatus;
if (ws < 0) {
compareAndSetWaitStatus(node, ws, 0);
}
//找到有效的next, 并unpark
Node tobeUnpark = node.next;
if (tobeUnpark == null || tobeUnpark.waitStatus > 0) {
//next为空或无效, 从尾到头遍历, 直到碰到最前的有效状态的节点
//这里不从头开始遍历是因为: 从头开始的话, 就是t.next一路遍历下去
//但是AQS是LCH的变种, next是优化, 不是原子性更新的, 不可靠
//见Doug Lea大师的论文: http://ifeve.com/aqs-2/ (3.3 队列一节)
//next链接仅是一种优化。如果通过某个节点的next字段发现其后继结点不存在(或看似被取消了)
//总是可以使用pred字段从尾部开始向前遍历来检查是否真的有后续节点。
//MCS队列和LCH队列的区别是: MCS是通过.next属性来链表, LCH是.prev属性, LCH轮询前节点状态, MCS前节点设置后置节点状态, 后置节点轮询自己状态
//则入队的时候LCH只需要先修改自己的prev, 在cas更新tail就好, 而MCS就需要先获取tail, 然后修改tail.next, 最好更新tail属性, 步骤更多, 同步更复杂
tobeUnpark = null;
for (Node t = tail; t != null && t != node; t = t.prev) {
if (t.waitStatus <= 0) {
tobeUnpark = t;
//这里不break, 是为了找到最接近head的有效节点, 来唤醒
//为啥不从头开始遍历, 而是从尾巴开始, next是优化, 不可靠
}
}
}
//唤醒
if (tobeUnpark != null) {
LockSupport.unpark(tobeUnpark.thread);
}
}
//共享模式的释放, 链表有超过一个节点, 就进行释放逻辑
private void doReleaseShared() {
//释放逻辑: 头节点状态变为0或PROPAGATE, 如果有继任者, 则唤醒
for (;;) {
Node h = head;
if (h != null && h != tail) {//有头节点且有继任者
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {//头节点状态为SIGNAL, 则改为0, 然后唤醒继任者
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
continue;
}
//唤醒继任者, 退出循环
unparkSuccessor(h);
}
//头节点状态为0, 则改为PROPAGATE 然后退出循环 , 改为PROPAGATE表示并非(0, -1, -2), 其他地方并直接未用到这个状态,
//但是其他地方通过waitStatus < 0 来进行一些处理
else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
continue;
}
//TODO:这里会不会存在其他线程吧Node状态改为非0和非PROPAGATE, 导致死循环
}
//完成释放, 这是h的状态为0或者PROPAGATE
if (h == head) {
break;
}
}
}
//设置node为头节点, 检查继任者是不是共享模式, 如果是, 且(propagate值大于0或继任者PROPAGATE被设置)
//则共享释放(head状态设置为0或-3, 唤醒继任者) : 增殖
//propagate: tryAcquireShared的返回值, 一般是state减去acquires, 大于0表示还可以继续try.
private void setHeadAndPropagate(Node node, long propagate) {
Node h = head;//旧的head
setHead(node);//设置新的头节点
//1.propagate > 0 , 表示还可以继续共享申请, doReleaseShared唤醒共享类型的后继者继续试
//2.(propagate == 0) && (h.waitStatus < 0), 前head状态小于零, 对于唤醒来说-1和-3没区别, 状态为0, 表示没有后继结点需要唤醒
if (propagate > 0 //还可以继续tryAcquireShared, 可能等于0
|| h == null || h.waitStatus < 0 //原来的head等待状态为PROPAGATE 猜测, 前head已经release了, 所以这里可以继续unpark
|| (h = head) == null || h.waitStatus < 0) { //新的head等待状态小于0
//下一个节点不为空, 且是共享模式, 就释放(头节点状态变为0,-3, 唤醒继任者, 如果有的话)
Node s = node.next;
if (s == null || s.isShared()) {
doReleaseShared();//感觉里面的逻辑和unpark很想
}
}
}
//取消进行中的acquire
private void cancelAcquire(Node node) {
if (node == null) {
return;
}
//减少不必要的唤醒
node.thread = null;
//找到node前面第一个有效的pred节点
Node pred = node.prev;
while (pred.waitStatus > 0) {
node.prev = pred = pred.prev;
}
Node predNext = pred.next;
node.waitStatus = Node.CANCELLED;
//node为tail节点, 则更新tail为有效的前驱节点
if (node == tail && compareAndSetTail(node, pred)) {
//设置tail成功后, 修改tail.next为null, 失败没关系(可能有新的节点入队列了)
compareAndSetNext(pred, predNext, null);
}
//node不是tail, 表示node后面有节点可能要唤醒, 如果不需要唤醒, 则更新下队列就好
else {
int ws;
if (pred != head //1.1
&& ((ws = pred.waitStatus) == Node.SIGNAL //2.1
/* */|| (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) //2.2
&& pred.thread != null //3.1
) {
//1.1.非首节点(意味着可能不需要唤醒后继节点)
//2.1.pred状态为SIGNAL, 意味着不用修改状态为SIGNAL
//2.2.pred状态不为SIGNAL, 则修改为SIGNAL, 标记后续节点要唤醒, 因为走到这里, 表示node不为tail(前面的if判断).
//3.1.pred.thread不为空(为空就表示pred被取消了或成head了, 这时就要唤醒后继了)
//满足1,2,3表示, 后继的节点不需要唤醒, 只要更新下队列, 避免多余的唤醒
//将node的next移动到prev上去, 完成node的出队, (如果next有且有效的话)
Node next = node.next;
if (next != null && next.waitStatus <= 0) {
compareAndSetNext(pred, predNext, next);
}
}
else {
//1.首节点 -> 意味着release后, 唤醒的是当前节点, 而当前节点已经cancal了, 需要传播下去, 唤醒node.next后继结点, 否则会导致后续节点没人去唤醒
//2.修改为pred状态为SIGNAL失败(可能是prev被(成head然后realease了)或(cancel)了) -> SIGNAL标记后继结点可以安全的park了, 标记失败, 则需要唤醒
//3.pred.thread为空(为空就表示pred被取消了或成head了, 这时就要唤醒后继了) -> 唤醒吧, 否则唤醒链到这里就断了, 后续节点没人唤醒了
//node的出队, 交给node.next = node, unparkSuccessor里面unpark, 然后后面的节点会将node出队列,
//走到这里说明pred的pred要么为null(head), 要么无效
//如果这里不唤醒的话, 可能head解锁的时候, 当前节点正再取消, 导致唤醒没有传播下去, 造成死锁
unparkSuccessor(node);
}
//通过将next指向自己, 标记node被取消, 简化isOnSyncQueue的实现
node.next = node; // help GC
}
}
//acquire失败后, 检查并更新pred的状态
//true:线程需要阻塞
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL) {
//表示前驱节点状态已经被标记为SIGNAL状态了, 我可以放心阻塞了.
return true;
}
if (ws > 0) {
//取消状态, 跳过取消的前驱节点, 返回false,
//方法外层会继续重试.
do {
node.prev = pred = pred.prev;
}
while (pred.waitStatus > 0);
}
else {
//前驱状态满足(0 or CONDITION or PROPAGATE)情况下啊, 更新前驱节点状态为SIGNAL,
//意思就是, 我这里tryAcquire失败了, 要阻塞了, 标记下前驱节点状态为SIGNAL, 好在后面唤醒我.
//这里不需要判断是否修改成功, 因为外部是循环, 所以等待下一次进入此方法就行了, 返回false, 继续重试.
//设置完成后, 外层会继续尝试一次tryAcquire
//从这里可以看出SIGNAL和PROPAGATE和0的区别在于, 状态为SIG后, 就park, 而0和-3需要再试一次
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
//等待, 直到前驱节点为head, 且tryAcquire成功
//模式为, 检查资源, 不满足, 则通知前驱节点解锁后要唤醒我(前驱节点SIGNAL), 然后再次尝试获取资源, 再次获取失败, 且状态(SIGNAL)设置好了, 就可以安全的park了
//如果不做两次检查, 可能导致当prev.state还没有被设置为SIGNAL时, prev就已经unlock了, 这时没有唤醒后继结点, 而后继结点刚刚设置完prev.state, 直接park了, 导致一直不会被唤醒.
//while(!tryAcquire()){
// prev.state = SIGNAL;
// if(!tryAcquire()){
// park();
// }else{
// 获取到锁的逻辑, 比如这里就是设置head
// break;
// }
//}
//这里的过程类似上面, 大概就是设置完唤醒标记后, 会再次检查是否满足申请条件
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//前驱节点为首节点, 则tryAcquire, 成功就更新head, 返回
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return interrupted;
}
//当前驱节点不为head,
//多次调用shouldParkAfterFailedAcquire后
//能将node的前驱节点更新为有效的节点, 且前驱状态为-1
//或者满足前面的if, 跳出循环
if (shouldParkAfterFailedAcquire(p, node) //更新node前驱的状态
&& parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
//嘛, 这里应该是走不到的, 除非异常了
cancelAcquire(node);
}
}
}
//acquireQueued的Interruptibly版本
private void doAcquireInterruptibly(int arg) throws InterruptedException {
//加入链表, 如果链表为空, 则head为new Node();
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node)//
&& parkAndCheckInterrupt()) {
throw new InterruptedException();
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
//加了超时处理
private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
if (nanosTimeout <= 0L) {
return false;
}
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0l) {
return false;//超时
}
//要等待, 且等待时间超过阀值, 太短的话, 没必要park
if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) {
LockSupport.parkNanos(nanosTimeout);
}
//中断状态处理
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
//共享模式的非中断Acquires
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) {
//r为正:表示共享申请成功, 且还有余量, 后面的可以继续申请, 0:表示共享申请成功, 但是没有余量, 后续申请要阻塞等待, r为负:表示共享申请失败
int r = tryAcquireShared(arg);
if (r >= 0) {
//设置node为head, 并增殖
setHeadAndPropagate(node, r);
p.next = null;
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null;
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
throw new InterruptedException();
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
private boolean doAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
if (nanosTimeout <= 0l) {
return false;
}
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null;
failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0l) {
return false;
}
if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) {
LockSupport.parkNanos(this, nanosTimeout);
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
}
public final void acquireInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
if (!tryAcquire(arg)) {
doAcquireInterruptibly(arg);
}
}
public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout);
}
//释放逻辑, 返回值为tryRelease结果
public final boolean release(int arg) {
if (tryRelease(arg)) {//释放成功
Node h = head;
//当没有竞争时, head是为空的, 当有竞争时, head被后面来的线程创建, 并加入队列,
//然后后续节点在park前修改状态, 在shouldParkAfterFailedAcquire()中修改状态(0 -> -1).
//所以这里, head会空的话, 不用unpark继任.
//所以这里, head状态为0, 表示继任节点还未park, 不用unpark继任.
//head不可能为cancel, 所以这里等价于h.waitStatus < 0
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
return false;
}
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) {
//try失败, 则一直试, 直到成功
doAcquireShared(arg);
}
}
public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
if (tryAcquireShared(arg) < 0) {
doAcquireSharedInterruptibly(arg);
}
}
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
return tryAcquireShared(arg) >= 0 //try成功直接返回, 失败继续试
|| doAcquireSharedNanos(arg, nanosTimeout);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
//设置头节点, 并释放thread和prev的引用, 因为已经不需要了, GC友好.
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() {
Node p = prev;
if (p == null) {
throw new NullPointerException();
}
else {
return p;
}
}
Node() {}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset(MyAqs.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset(MyAqs.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset(MyAqs.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("next"));
} catch (Exception ex) {
throw new Error(ex);
}
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}
private static final boolean compareAndSetNext(Node node, Node expect, Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
}