Java布尔表达式并发行为:AtomicInteger比较的原子性疑问
让我把这个问题拆解清楚,一步步给你讲明白:
表达式 first.get() == second.get() 的具体求值过程
这个表达式的执行是顺序分步的,具体流程如下:
- 先执行左侧操作数:调用
first.get(),这会原子性地读取first这个AtomicInteger的当前值,返回一个普通的int数值。 - 接着执行右侧操作数:调用
second.get(),同样原子性地读取second的当前值,返回另一个int数值。 - 最后执行相等判断:把前两步得到的两个
int值做==比较,将结果赋值给equal变量。
求值期间变量值会不会发生变化?
答案是完全可能发生变化,这个表达式不具备原子性,也不会生成所谓的“变量快照”。
举个具体场景你就能直观理解:
- 初始状态:
first和second的值都是5。 - 线程A开始执行表达式:先调用
first.get()拿到了5,这时候线程B突然修改了second的值为6。 - 线程A继续执行
second.get(),拿到的就是6了,最后比较5和6,结果equal为false——哪怕一开始两个变量的值是相等的。
本质原因是:first.get()和second.get()只是各自单独的原子操作,但这两个操作之间没有任何同步保护,中间存在一个时间窗口,其他线程完全可以在这个间隙修改其中一个变量的值。整个表达式的执行是两个独立原子操作加一次比较,整体并不是原子的。
如果想要原子性比较两个值怎么办?
如果你的需求是原子性地判断两个AtomicInteger在同一时刻是否相等,需要额外的同步手段,比如:
- 用
synchronized块把两个get操作包裹起来,确保同一时间只有一个线程能访问这两个变量:
boolean equal; // someLockObject可以是类实例本身,或者专门定义的锁对象 synchronized (someLockObject) { equal = first.get() == second.get(); }
- 或者调整数据结构,用
AtomicReference把两个值包装成一个不可变对象,这样可以原子性地读取整个状态,但这需要你重新设计存储方式。
内容的提问来源于stack exchange,提问作者alxg2112
相关产品推荐
相关产品推荐

