Dha*_*amy 4 java multithreading java-memory-model happens-before
我有以下代码
class VolatileCount {
volatile int count;
Object lock = new Object();
public void increment() {
synchronized (lock) {
count = count + 1;
}
System.out.print(" " + count);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我increment()从多个线程调用相同的对象,我会得到以下输出(可能在您的机器上有所不同)
2 3 2 5 4 8 8 6 11 13 10 9 15 14 12 20 19
Run Code Online (Sandbox Code Playgroud)
看看我认为发生的重复数字似乎被破坏了,因为考虑前三个数字(2 3 2),如果线程看到3,则发生增量,并且因为变量是易变的,所以它的值应该是3或更多但是在任何线程中都不能为2.
但是,打印线似乎已在这里重新排序,重新排序该行是否正确?我在这里错过了什么?我运行JDK 7(Eclipse)
更新
因为你似乎想要解释"2 3 2"的具体情况
i(现在为1)i(现为2)i(X加载2)i(Y加载2)i,读数i,打印i(打印3)关键是:System.out.print(" " + count)不是原子的.执行易失性读取之后和打印值之前,线程可以被抢占.
如果要防止打印重复值,则必须在锁内执行volatile读取:
public void increment() {
int localCount;
synchronized (lock) {
count = count + 1;
localCount = count; // volatile load
}
System.out.print(" " + localCount);
}
Run Code Online (Sandbox Code Playgroud)
这不会阻止值无序打印.为了按顺序打印它们,没有重复,你也必须移动print到锁中.
print语句在锁外.考虑一下里面 运行的代码System.out.print(" " + count).
iprint参数并对变量执行易失性读取count,并加载该值2.ii(现在是3),调用运行完成的print方法.print完成,打印2.这会使数字显示不按顺序,例如"3 2 4".
在下列情况下,某些数字也可能重复
i(现在为2)i(现在为3)i(3)i(3)