就是看了源码你就知道,不管是独占锁还是共享锁,都是设置自己的前驱为 SIGNAL 来当作闹钟的,所以这个地方直接 h.waitStatus == SIGNAL 不行吗?
难道说,独占锁的释放里真的有什么场景,使得头节点的状态不是 0,也不是 SIGNAL ?
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)//这里
unparkSuccessor(h);
return true;
}
return false;
}
1
brust 2020-06-04 09:26:42 +08:00
头节点好像状态不是 0
|
2
Aresxue 2020-06-04 10:15:31 +08:00
CANCELLED,值为 1,表示当前的线程被取消;
SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是 unpark ; CONDITION,值为-2,表示当前节点在等待 condition,也就是在 condition 队列中; PROPAGATE,值为-3,表示当前场景下后续的 acquireShared 能够得以执行; 值为 0,表示当前节点在 sync 队列中,等待着获取锁。 最简单的头结点锁包含的线程被取消了 |
3
amiwrong123 OP @Aresxue
你的意思是 h.waitStatus != 0 是为了对应头结点为 CANCELLED 的情况吗,纳尼,这不可能吧。 要知道头结点的线程其实就是 已经获得了独占锁的线程,也就是 AQS 的 exclusiveOwnerThread 成员。而取消这个动作,只是针对于 在等待队列中的节点才会执行的动作,我头结点都已经获得了独占锁,是不可能执行取消动作的。 |
4
amiwrong123 OP @brust
是的,一般就为 SIGNAL 。 |
5
Aresxue 2020-06-04 15:37:58 +08:00
@amiwrong123 只是举例,但像你说的不可能确实是不可能为 CANCELLED, 再分析下 PROPAGATE 是用在共享锁里面的,感觉这个!=0 可能是考虑了 CONDITION 这种情况,看的太久了已经忘了。。。你可以去看下 CONDITION 情况下有没有用到 release,如果没有用到那么这里就是等价于 SIGNAL 的
|
6
bigbyto 2020-06-04 17:14:04 +08:00
考虑这样一种场景。
Thread A 获得锁,正在执行耗时任务,结束后,开始执行 unlock,注意这时候还没完全释放 lock 。 此时 Thread B 调用 lock 想获得锁,但因为 Thread A 还没释放,tryAcquire 会失败,会进去 acquireQueued,看下面的代码。 if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC return interrupted; } 请注意,此时 head 是由 Thread B 创建,不过因为 Thread B 并未 park,此时状态为 0,因此不需要 Thread A 去执行 unpark 。 |
7
bigbyto 2020-06-04 17:17:43 +08:00
理解错意思了,无视我楼上的回答
|
8
amiwrong123 OP @Aresxue
condition 这两天我就会去看,不过估计也不可能是它。哎,aqs 里面好多细节,就是不知道为什么这么写 |
9
hideon 2023-07-02 15:34:21 +08:00
楼主还在吗,不好意思挖坟了,我想问一下 h.waitStatus != 0 这里,我看源码:
将前驱节点 waitStatus 设置为-1 ( Node.SIGNAL )时机是 shouldParkAfterFailedAcquire ,此时节点已经完成了尾插法 addWaiter (如下整个方法已完成) 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; } } } } 为什么 release 方法还需要从后往前扫一遍? 貌似不存在未执行 t.next = node 的情况 |