@@ -878,14 +878,14 @@ AQS 中,Node 节点的 `PROPAGATE` 就是为了处理并发场景下可能出
878
878
879
879
有了 ` PROPAGATE ` 状态,就可以避免线程 ` T2 ` 无法被唤醒的情况。对应时刻表如下:
880
880
881
- | 时刻 | 线程 T1 | 线程 T2 | 线程 T3 | 线程 T4 | 等待队列 |
882
- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------- | ------------------------------------ |
883
- | 时刻 1 | 等待队列 | 等待队列 | 持有资源 | 持有资源 | ` head(-1) -> T1(-1) -> T2(0) ` |
884
- | 时刻 2 | (执行)被唤醒后,获取资源,但未来得及将自己设置为 ` head ` 节点 | 等待队列 | (执行)释放资源 | 持有资源 | ` head(0) -> T1(-1) -> T2(0) ` |
885
- | 时刻 3 | 未继续向下执行 | 等待队列 | 已退出 | (执行)释放资源。此时会将 ` head ` 节点状态由 ` 0 ` 更新为 ` PROPAGATE ` | ` head(PROPAGATE) -> T1(-1) -> T2(0) ` |
886
- | 时刻 4 | (执行)将自己设置为 ` head ` 节点 | 等待队列 | 已退出 | 已退出 | ` head(-1,线程 T1 节点) -> T2(0) ` |
887
- | 时刻 5 | (执行)由于 ` head ` 节点状态为 ` PROPAGATE < 0 ` ,因此会在 ` setHeadAndPropagate() ` 方法中唤醒后续节点,此时将新的 ` head ` 节点的状态由 ` SIGNAL ` 更新为 ` 0 ` ,并且唤醒线程 ` T2 ` | 等待队列 | 已退出 | 已退出 | ` head(0,线程 T1 节点) -> T2(0) ` |
888
- | 时刻 6 | 已退出 | (执行)线程 ` T2 ` 被唤醒后,获取到资源,并将自己设置为 ` head ` 节点 | 已退出 | 已退出 | ` head(0,线程 T2 节点) ` |
881
+ | 时刻 | 线程 T1 | 线程 T2 | 线程 T3 | 线程 T4 | 等待队列 |
882
+ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------- | ------------------------------------ |
883
+ | 时刻 1 | 等待队列 | 等待队列 | 持有资源 | 持有资源 | ` head(-1) -> T1(-1) -> T2(0) ` |
884
+ | 时刻 2 | (执行)被唤醒后,获取资源,但未来得及将自己设置为 ` head ` 节点 | 等待队列 | (执行)释放资源 | 持有资源 | ` head(0) -> T1(-1) -> T2(0) ` |
885
+ | 时刻 3 | 未继续向下执行 | 等待队列 | 已退出 | (执行)释放资源。此时会将 ` head ` 节点状态由 ` 0 ` 更新为 ` PROPAGATE ` | ` head(PROPAGATE) -> T1(-1) -> T2(0) ` |
886
+ | 时刻 4 | (执行)将自己设置为 ` head ` 节点 | 等待队列 | 已退出 | 已退出 | ` head(-1,线程 T1 节点) -> T2(0) ` |
887
+ | 时刻 5 | (执行)由于 ` head ` 节点状态为 ` PROPAGATE < 0 ` ,因此会在 ` setHeadAndPropagate() ` 方法中唤醒后续节点,此时将新的 ` head ` 节点的状态由 ` SIGNAL ` 更新为 ` 0 ` ,并唤醒线程 ` T2 ` | 等待队列 | 已退出 | 已退出 | ` head(0,线程 T1 节点) -> T2(0) ` |
888
+ | 时刻 6 | 已退出 | (执行)线程 ` T2 ` 被唤醒后,获取到资源,并将自己设置为 ` head ` 节点 | 已退出 | 已退出 | ` head(0,线程 T2 节点) ` |
889
889
890
890
### AQS 资源释放源码分析(共享模式)
891
891
@@ -922,7 +922,7 @@ protected final boolean tryReleaseShared(int releases) {
922
922
923
923
如果更新成功,则证明资源释放成功,会进入到 ` doReleaseShared() ` 方法。
924
924
925
- ` doReleaseShared() ` 方法在上边 ` doAcquireShared() ` 时已经分析过,这里不再重复 。
925
+ ` doReleaseShared() ` 方法在前文获取资源(共享模式)的部分已进行了详细的源码分析,此处不再重复 。
926
926
927
927
## 常见同步工具类
928
928
0 commit comments