相关状态
//标志节点已被取消
static final int CANCELLED = 1;
//标志后继节点处于等待状态
static final int SIGNAL = -1;
acquire(int arg)
获取独占资源
public final void acquire(int arg) {
//1、尝试获取独占资源 成功返回 失败进行下一步
// 2、生成节点,将其添加进同步队列 竞争成功返回
//3、若线程在不可中断的时候被中断了
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//4、处理中断
selfInterrupt();
}
tryAcquire(arg)
在AbstractQueuedSynchronizer的子类中自行重写的获取资源的方法
例:
@Override
public boolean tryAcquire(int acquires){
if (compareAndSetState(0,1)){
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
compareAndSetState(int expect, int update)
protected final boolean compareAndSetState(int expect, int update) {
//compareAndSwapInt是Java的native方法,并不由Java语言实现。
//方法的作用是,读取传入对象o(this)在内存中偏移量为offset位置的值与期望值expected作比较。
//相等就把update值赋值给offset位置的值。方法返回true。不相等,就取消赋值,方法返回false。
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
addWaiter(Node mode)
/**
* 往等待队列里添加新节点
*row:605
**/
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;
//若尾节点不为null
if (pred != null) {
node.prev = pred;
//尝试将该节点放入队列尾部
//成功 直接返回
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//队列未初始化 或 添加尾节点存在竞争
//通过自旋保证尾节点的正确填入
enq(node);
return node;
}
enq(final Node node)
/*
* 新添一个节点到原队列尾部
* row:583
*/
private Node enq(final Node node) {
//死循环,确保队列初始化,且将新节点添加到队列尾部
for (;;) {
Node t = tail; //获取尾节点
//尾巴节点为null证明队列尚未初始化
if (t == null) { // Must initialize
//实例化一个Node,令头尾节点都指向它
if (compareAndSetHead(new Node()))
tail = head;
} else {
//将新节点上一个节点指向原尾节点
node.prev = t;
//将新节点设置为尾节点
if (compareAndSetTail(t, node)) {
//将让原尾节点指向新节点
t.next = node;
return t;
}
}
}
}
acquireQueued(final Node node, int arg)
inal boolean acquireQueued(final Node node, int arg) {
//结果标记
boolean failed = true;
try {
boolean interrupted = false;
//死循环(自旋)让其成为头节点 独占锁
for (;;) {
//获取当前节点的上一个节点
final Node p = node.predecessor();
//若上一个节点为头节点 且 尝试独占资源成功
if (p == head && tryAcquire(arg)) {
//设置当前节点为头节点
setHead(node);
p.next = null; // help GC 解除引用关系
failed = false;
return interrupted;
}
//查看唤醒闹钟设好了没有(查看当前其前驱节点的状态是否为SIGNAL)
//阻塞该线程
//如果不可中断的情况下被中断了,那么会从park()中醒过来,发现拿不到资源,从而继续进入park()等待
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
//如果等待过程中没有成功获取资源(如timeout,或者可中断的情况下被中断了),那么取消结点在队列中的等待
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire(Node pred, Node node)
/*
*如果pred的后继都能获取锁 返回true
*如果不能,删除已被取消的节点 返回false
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//获取前一个节点的状态
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
//node节点和其后的节点处于等待状态
return true;
if (ws > 0) {
//前一个节点处于取消状态
do {
//将前一个节点从链表中删除
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
//waitStatus must be 0 or PROPAGATE(-3)
//将前一个节点的状态设为SIGNAL(-1)
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
parkAndCheckInterrupt()
private final boolean parkAndCheckInterrupt() {
//阻塞当前线程的执行
LockSupport.park(this);
//获取线程中断状态后,并重置中断状态为false
return Thread.interrupted();
}
release(int arg)
释放已占有的资源
public final boolean release(int arg) {
//调用自定义方法 尝试释放资源
if (tryRelease(arg)) {
Node h = head;
//同步队列中还有线程在等待
if (h != null && h.waitStatus != 0)
//删除当前节点
unparkSuccessor(h);
return true;
}
return false;
}
unparkSuccessor(Node node)
//638
//将当前节点的状态设为0(初始值),唤醒该节点的下一个节点
private void unparkSuccessor(Node node) {
//获取状态
int ws = node.waitStatus;
//若状态不是初始值
if (ws < 0)
//将状态设为初始值
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
//如果下一个节点为null或已被取消
if (s == null || s.waitStatus > 0) {
//释放该节点
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);
}