线程安全性
在线程安全类的实例上顺序或并发执行的任何一组操作都不会导致实例处于无效状态。
StatelessFactorizer 是无状态的:它没有字段,也没有引用其他类的字段。特定计算的瞬态仅存在于存储在线程堆栈中的局部变量中,并且只能由执行线程访问。一个访问 StatelessFactorizer 的线程不能影响另一个线程访问同一个 StatelessFactorizer 的结果;因为这两个线程不共享状态,所以就好像它们在访问不同的实例一样。由于访问无状态对象的线程的操作不会影响其他线程中操作的正确性,因此无状态对象是线程安全的。
原子性
类似于count++这样的语句,由于其紧凑的语法,它可能看起来像一个单一的动作,但它不是原子的,这意味着它不会作为一个单一的、不可分割的操作来执行。相反,它是三个离散操作序列的简写:获取当前值,将其加一,然后写回新值。这是读取-修改-写入操作的示例,其中结果状态是从先前状态派生的。
竞态条件
UnsafeCountingFactorizer 有几个竞态条件,导致其结果不可靠。当计算的正确性取决于运行时多个线程的交替执行顺序时,就会出现竞态条件;换句话说,获得正确答案取决于幸运的时机。最常见的竞态条件是check-then-act,它使用可能过期的观测结果来决定下一步做什么。
懒惰加载中的竟态条件(例子)
为了确保线程安全,check-then-act 操作(如惰性初始化)和 read-modify-write 操作(如增量)必须始终是原子的。我们将check-then-act操作和read-modify-write 操作统称为复合动作:必须以原子方式执行以保持线程安全的操作序列。
对于read-modify-write 操作,我们可以使用AtomicLong来保证其线程安全: