一系列的操作,要么全部执行成功,要么全部不执行,不会出现执行一半的情况,是不可分割的。
注意:i++ 不是原子性的,可以用 synchronized 实现原子性。
除 long 和 double 之外的基本类型(int, byte, boolean, short, char, float)的赋值操作。
所有引用(reference)的赋值操作,不管是 32 位的机器还是 64 位的机器。
java.concurrent.Atomic.* 包中所有类的原子操作。
下面截图内容来自官方文档:https://docs.oracle.com/javase/specs/jls/se21/html/jls-17.html#jls-17.7
官方文档总结:long 和 double 是 64 位的值。出于Java编程语言内存模型的目的,对 non-volatile 的 long 或 double 值的单次写入被视为两次单独的写入:每次写入一半,即每次写入 32 位。这可能会导致线程从一次写入中看到 64 位值的前 32 位,而从另一次写入中看到后 32 位。可以使用 volatile 关键字解决该问题。
在 32 位的JVM上,long 和 double 的操作不是原子的,但是在 64 位的JVM上是原子的。
在实际开发中,商用Java虚拟机早就考虑到这一点了,会避免这种问题的发生,自动保证 long 和 double 写入时的原子性。对我们而言,不必担心 long 和 double 在 32 位机器上写入时的原子问题。
简单地把原子操作组合在一起,并不能保证整体依然具有原子性。