@@ -878,14 +878,14 @@ AQS 中,Node 节点的 `PROPAGATE` 就是为了处理并发场景下可能出
878878
879879有了 ` PROPAGATE ` 状态,就可以避免线程 ` T2 ` 无法被唤醒的情况。对应时刻表如下:
880880
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 节点) ` |
889889
890890### AQS 资源释放源码分析(共享模式)
891891
@@ -922,7 +922,7 @@ protected final boolean tryReleaseShared(int releases) {
922922
923923如果更新成功,则证明资源释放成功,会进入到 ` doReleaseShared() ` 方法。
924924
925- ` doReleaseShared() ` 方法在上边 ` doAcquireShared() ` 时已经分析过,这里不再重复 。
925+ ` doReleaseShared() ` 方法在前文获取资源(共享模式)的部分已进行了详细的源码分析,此处不再重复 。
926926
927927## 常见同步工具类
928928
0 commit comments