AtomicInteger是如何实现线程安全的?

问题描述 投票:0回答:3

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

根据我对原子整数的理解,它的工作原理是“比较和交换”算法。 我无法理解当两个线程尝试完全相同的时间增加同一个原子变量时,这将如何工作。 假设我已经定义了

AtomicInteger var = 1

,并且它被两个线程

Thread_1
Thread_2
使用。当两个线程尝试同时增加
var
时会发生什么
T1
。 我知道这种情况很少见,但如果发生怎么办?在比较和交换中,它在单个原子操作中读取和更新变量,并检查内存中的值。那么,如果在时间
T1-1
,var 的值为 5 并且
Thread1
Thread2
都会开始递增它呢? 哪一个会失败?这会是随机行为吗?或者我错过了一些非常基本的东西。
    

java multithreading atomicinteger
3个回答
9
投票

您可以使用比较和交换显式实现增量操作:

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

CPU 保证 
compareAndSwap

是原子的(会有一个本机实现)。

如果两个线程同时命中此 

compareAndSwap

,则只有其中一个线程会“获胜”,接收

true
作为
compareAndSwap
调用的结果,因此循环停止。
另一个线程将“失败”,并收到 

false

作为结果,因此将再次循环:它读取一个新值,然后再次尝试 CAS。如果成功(因为没有其他线程同时尝试执行此操作,或者它“赢得”了另一个线程),则循环将停止;否则,它只会重试。

    


3
投票
那么如果在时间 T1-1 时 var 的值为 5 并且 Thread1 和 Thread2 都将开始递增它呢?

其中一个将成功执行与
5

的当前值和

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

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


2
投票

© www.soinside.com 2019 - 2024. All rights reserved.