没有同步或易失性的java内存可见性
如果没有“synchronized”或“volatile”关键字,那么一个线程所做的更改将永远不会被另一个线程看到(或不显示),这是正确的吗?我在多核平台上多次运行以下程序,结果不同。有时程序永远不会终止,这是预期的场景。但有时它会打印“1”
JDK:jdk1。8.0_73
OS:CentOS Linux 7.1.1503版
public class VolatileTest implements Runnable {
private int i = 0;
public void run() {
i++;
i++;
}
public int get() {
return i;
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
VolatileTest volatileTest = new VolatileTest();
executorService.execute(volatileTest);
while (true) {
int i = volatileTest.get();
if (i % 2 != 0) { //
System.out.format("i: %s \n", i);
System.exit(0);
}
}
}
}
# 1 楼答案
这不正确,这个问题已经得到了回答(this)
run方法不是原子的/线程安全的/同步的,因此,赋值
int i = volatileTest.get();
可以得到0到2的值,这很容易理解。为了达到你想要的效果,你应该获得一个lock
并在双增量后重新分配它,或者只把关键字synchronized
放在方法签名中# 2 楼答案
volatileTest.get()
的输出可以是0, 1, or 2
,因为没有同步,并且run方法不是原子的。此外,每个i++
操作都不是原子操作因此,这两种情况都适用:
i++
操作完成,get的结果是1李>i++
指令都已完成,get()
返回2,因此陷入无限循环李>