是JVM允许指令重新排序,周围的AtomicInteger调用
它是安全的假设,(AtomicInteger a).addAndGet(-1)
之前的代码将在调用之前一直执行的,即JVM将不重新排序围绕addAndGet
调用的指令?是JVM允许指令重新排序,周围的AtomicInteger调用
如果是的话,是可以安全地假设其他线程检查同一AtomicInteger
实例的状态(例如if (a.compareAndSet(0, -1))
)将看到的一切addAndGet
调用之前的第一个线程发生了变化?
它是安全的假设,之前的代码(的AtomicInteger 一).addAndGet(-1)将总是此调用之前执行,即JVM 不会重新排序围绕addAndGet调用的指令?
是的,这是正确的。 addAndGet
将发出一个易变的商店(或类似的),因此其他加载和存储不能在其下面重新排序。
编辑:谢谢Soitrios链接https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html,这表明有一个建立秩序为你。
- 获得读取volatile变量的内存效果。
- 集具有写入(分配)易失性变量的内存效果。
- compareAndSet和所有其他读取和更新操作(如getAndIncrement)都具有读取和写入易失性变量的内存效果。
不仅JVM被阻止,CPU也被阻止了。即CPU也可以重新排序指令的执行。 –
@John Vint,你是否同意上面关于“if(a.compareAndSet(...))”内部的@Holger注释,你只能保证看到线程所做的更改,期望值”? – Gedrox
是的,我同意这种说法。由于我们不能说失败的线程成功写入,它永远不会发出易失性存储。因此,该线程的写入和连续线程的读取之间没有同步。 –
我相信你只能依赖set发生的事实 - 在得到特定的AtomicInteger之前。 –
要挑剔,你从来没有任何关于何时被执行的保证,而是关于*可观察到的效果*。但是这实际上是你感兴趣的。你不应该忽略'if(a.compareAndSet(...))'中的内容,你只能保证看到线程所做的改变,值。所以你必须确保没有多种方法来达到这个价值...... – Holger
@Holger,在这种情况下可能会有什么帮助?我必须看到所有线程的变化减少了'a'的值,最后一个使其为零的线程必须与从所有线程收集的数据一起工作。 – Gedrox