java - AtomicInteger 如何是线程安全的
问题描述
我正在阅读一些关于 Java 中原子变量的文档。正如到处都写的那样,AtomicInteger 应该是线程安全的。
根据我对原子整数的理解,它的工作原理是比较和交换算法。当两个线程尝试在完全相同的时间增加相同的原子变量时,我无法理解这将如何工作。
说我有定义AtomicInteger var = 1
,这被两个线程Thread_1
和Thread_2
. var
当两个线程同时尝试增加 时会发生什么T1
。我知道这将是罕见的情况,但如果它发生了怎么办。在比较和交换中,它在单个原子操作中读取和更新变量,并检查内存中的值。那么如果在 time T1-1
, var 的值是 5 并且两者都Thread1
将Thread2
开始递增呢?哪一个会失败?会是随机行为吗?或者我错过了一些非常基本的东西。
解决方案
比较和交换在 CPU 级别是原子的。
您可以使用比较和交换显式实现增量操作:
int value;
do {
value = var.get();
} while (!var.compareAndSwap(value, value + 1));
CPU 保证它compareAndSwap
是原子的(会有一个本机实现)。
如果两个线程同时命中这个compareAndSwap
,只有其中一个会“获胜”,true
作为compareAndSwap
调用的结果接收,所以循环停止。
另一个线程将“丢失”并接收false
结果,因此将再次循环:它读取一个新值,然后再次尝试 CAS。如果成功(因为没有其他线程同时尝试执行此操作,或者它“胜过”另一个线程),则循环停止;否则,它只是再次尝试。
推荐阅读
- c++ - vector 如何在特定位置调用复制构造函数?
- javascript - 与 mysql 连接的 hapi.js 未在浏览器上显示该值
- sql - 如何写垂直列
- java - OWASP java-html-sanitizer - 未封闭标签的策略
- pandas - 如何使用 pandas group-by 仅对后续/不间断的元素进行分组?
- keycloak - 反向代理下的keycloak/mod_auth_openidc
- python - 如何将向量添加到矩阵
- c - 如何在以下案例设备树中访问单元格属性
- javascript - 使用 JSON.parse(data) 后如何访问通过 AJAX 响应获取的数组值?
- html - 如何在一条线上垂直居中一个圆?