AtomicInteger如何是线程安全的

时间:2019-05-20 07:40:49

标签: java multithreading atomicinteger

我正在阅读一些有关Java中原子变量的文档。 随处可见,AtomicInteger应该是线程安全的。

据我对原子整数的理解,它基于比较和交换算法的原理工作。 如果两个线程试图在同一时间递增相同的原子变量,我无法理解如何工作。

说我已经定义了AtomicInteger var = 1,两个线程Thread_1Thread_2正在使用它。当两个线程都尝试同时var递增T1时会发生什么。 我知道这种情况很少见,但是如果发生的话该怎么办。在比较和交换中,它通过单个原子操作读取和更新变量,并从内存中检查值。因此,如果在时间T1-1时var的值为5,而Thread1Thread2都将开始递增呢? 哪一个会失败?会是随机行为吗?或我缺少一些非常基本的东西。

3 个答案:

答案 0 :(得分:5)

比较和交换在CPU级别是原子的。

您可以使用compare和swap显式实现增量操作:

int value = var.get();
while (!var.compareAndSwap(value, value + 1)) { 
  value = var.get();
}

CPU保证compareAndSwap是原子的(将是本机实现)。

如果两个线程同时命中该compareAndSwap,则只有一个线程将“获胜”,并由于true调用而收到compareAndSwap,因此循环停止。

另一个线程将“丢失”并接收false作为结果,因此将再次循环处理:它读取一个新值,然后再次尝试CAS。如果成功(因为没有其他线程同时尝试执行此操作,或者因为它“胜过”另一个线程),则循环停止;否则,它将再次尝试。

答案 1 :(得分:2)

这是典型的比赛情况。将此增量操作视为一间小门的小房间,只有一个人可以容纳并执行一些操作。设法进入此房间的两个人的第一个线程将执行增量操作。然后,当完成时,第二个=“不太幸运”线程将完成其工作。但重要的是,这两个操作的结果是一致的,因为它们不会并行执行增量操作。

答案 2 :(得分:2)

  

那么如果在时间T1-1处var的值为5,并且Thread1和Thread2都将开始递增它怎么办?

其中一个将成功执行比较与当前值5和新值6的比较和交换,另一个将失败并尝试使用值6和新值{ 7。它们不能同时使用当前值5和新值6来成功,它们是在CPU级别处理的。

即使它们运行在不同的内核上并且CAS操作完全在同一时间执行,仍然会有其中一项操作失败,这实际上是随机的(可能不取决于CPU的实现)。