for循环每次迭代是原子操作吗?AtomicBigInteger的incrementAndGet原子性分析
问题解答
核心结论
incrementAndGet方法对外表现的执行效果是原子的,完全线程安全- JVM 不会 保证for循环的每一次迭代是原子执行的,该实现的线程安全是靠CAS自旋逻辑保障,而非JVM对循环的原子性保证
具体原理说明
你看到的是Java中无锁原子操作的经典实现:自旋CAS(Compare And Swap),逻辑拆解如下:
- 循环内的三个操作
valueHolder.get()读当前值、current.add()计算累加后的值、compareAndSet()尝试更新,前两个操作都不是原子的,执行过程中完全可能被线程调度打断,也可能有多个线程同时执行到这两步、拿到同一个current值。 - 只有
compareAndSet是CPU硬件级别的原子操作:执行时会先校验valueHolder当前存储的值是不是和传入的current完全一致,是才会把值更新为next返回成功,否则直接返回失败。 - 死循环的作用就是更新失败时重试,重新读最新的值、重新计算、再尝试CAS,直到更新成功为止。
对外原子性的原因
从调用方的视角看,调用一次incrementAndGet要么不生效,要么就完整完成「值加1、返回新值」的效果,不会出现中间状态,也不会出现多线程同时调用导致累加丢失的问题,所以对外表现等价于原子操作。
内容的提问来源于stack exchange,提问作者eztam
相关产品推荐
相关产品推荐

