You need to enable JavaScript to run this app. 并发访问下AtomicBoolean出现连续同方向输出的原因
优惠活动
大模型
产品
解决方案
定价
更多

并发访问下AtomicBoolean出现连续同方向输出的原因

连续同方向输出的根本原因

核心误解:打印语句的字段含义

你代码中打印逻辑的实现如下:

System.err.println(super.getName() + "  "+ bool +"->" + top + ". i is " + i);

这里箭头左侧的bool是每个Toppler线程在构造时传入的固定常量属性,初始化后不会再改变,并不是翻转前的top变量值;箭头右侧才是代码执行到打印时刻的top实际值。你误以为箭头代表「top从左侧值翻转到右侧值」,实际上它只是把线程自身的固定布尔值、和当前时刻的top值做了字符串拼接。

分支逻辑漏洞

你的翻转操作是写在if判断内部的:

synchronized (top) {
    if (top.get() == bool) top.set(!top.get());
    System.err.println(super.getName() + "  "+ bool +"->" + top + ". i is " + i);
}

这意味着:

  • 只有当当前top值和线程自身的bool相等时,才会执行翻转操作
  • 当条件不满足时,代码完全不会修改top的值,但因为打印语句写在if块外部,无论是否触发翻转,都会照常执行打印。

结合实际输出的逻辑复现

你观察到的连续同方向输出,完全可以通过上述逻辑解释:
假设某一刻top的值为true,此时连续抢到synchronized锁的两个线程都是bool=false的类型:

  1. 第一个bool=false的线程拿到锁,判断top.get()=true,和自身的bool不相等,不执行翻转,直接打印[线程名] false->true(左侧是自己的固定bool值,右侧是当前top值true)
  2. 第二个bool=false的线程拿到锁,此时top仍然是true,依然不满足翻转条件,同样打印[线程名] false->true
    最终就出现了连续两行false->true的输出,但实际上整个过程中top的值从未发生变化。

你输出中出现的连续true->false也是同理:当top值为false时,连续抢到锁的两个bool=true的线程,都因为当前top值和自身bool不相等、不执行翻转操作,直接拼出true->false的打印内容,看起来就像连续发生了两次相同方向的状态翻转。

补充说明

  • 这里的synchronized锁已经完全保证了top操作的原子性与内存可见性,不存在AtomicBoolean工作机制异常的问题,本质是分支逻辑和打印设计的bug。
  • 这段代码中的synchronized锁其实是冗余的:AtomicBoolean本身提供的compareAndSet是原子操作,直接使用top.compareAndSet(bool, !bool)就可以完成条件翻转的逻辑,不需要额外加锁。

内容的提问来源于stack exchange,提问作者Andrew Levchenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.28 10:15:01