java - 变量的不同步读/写可能导致数据竞争?
问题描述
Jack Shirazi在Java Performance Tuning中写道:
这意味着变量的访问和更新是自动同步的(只要它们不是长整数或双精度数)。如果一个方法只包含一个变量访问或赋值,就没有必要为了线程安全而使其同步,并且出于性能考虑不这样做的所有理由。线程安全进一步扩展到独立于任何其他变量值访问或分配给变量的任何语句集。
根据上面的描述,操作 likeflag = true
总是原子的,不需要synchronize
.
但是,这里有另一篇文章将以下情况视为数据竞争:
class DataRaceExample {
static boolean flag = false;//w0
static void raiseFlag() {
flag = true;//w1
}
public static void main(String... args) {
ForkJoinPool.commonPool().execute(DataRaceExample::raiseFlag);
while (!flag);//r_i, where i ∈ [1, k), k may be infinite
System.out.print(flag);//r
}
}
作者说:
现在,所有执行都有数据竞争,因为标志不是易失的
这两篇文章之间的冲突让我很困惑。
解决方案
杰克·希拉兹错了。
原始变量的访问和更新,例如int
是原子的,但不是同步的。
因为它是原子的,所以可以通过使其成为完全线程安全的volatile
。否则,在不同内核上运行的其他线程可能会看到陈旧的值,因为CPU 缓存尚未刷新。
推荐阅读
- generics - 如何存储模型的收集路径?
- spring-boot - 如何在spring boot应用程序中避免“类路径资源[...]无法打开,因为它不存在”?
- asp.net-mvc - 401 Unauthorized : WWW-Authenticate: Bearer
- if-statement - 这个表达式有什么作用?Gui % (MainGui:=!MainGui) ? “隐藏”:“显示”
- dart - 子字符串直到字符串中第一次出现逗号
- html - 如何使用 vbscript 更改 div 类(html)
- python - 插入失败“OperationalError:没有这样的列”
- c# - 长的异步等待链会导致大量内存消耗吗?(理论上)
- java - 如何修复布局管理
- splunk - 如何配置 Splunk 转发器以从 stdout/stderr 而不是从文件中收集数据?