是JVM允许指令重新排序,周围的AtomicInteger调用

问题描述:

它是安全的假设,(AtomicInteger a).addAndGet(-1)之前的代码将在调用之前一直执行的,即JVM将重新排序围绕addAndGet调用的指令?是JVM允许指令重新排序,周围的AtomicInteger调用

如果是的话,是可以安全地假设其他线程检查同一AtomicInteger实例的状态(例如if (a.compareAndSet(0, -1)))将看到的一切addAndGet调用之前的第一个线程发生了变化?

+0

我相信你只能依赖set发生的事实 - 在得到特定的AtomicInteger之前。 –

+1

要挑剔,你从来没有任何关于何时被执行的保证,而是关于*可观察到的效果*。但是这实际上是你感兴趣的。你不应该忽略'if(a.compareAndSet(...))'中的内容,你只能保证看到线程所做的改变,值。所以你必须确保没有多种方法来达到这个价值...... – Holger

+0

@Holger,在这种情况下可能会有什么帮助?我必须看到所有线程的变化减少了'a'的值,最后一个使其为零的线程必须与从所有线程收集的数据一起工作。 – Gedrox

它是安全的假设,之前的代码(的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)都具有读取和写入易失性变量的内存效果。
+1

不仅JVM被阻止,CPU也被阻止了。即CPU也可以重新排序指令的执行。 –

+0

@John Vint,你是否同意上面关于“if(a.compareAndSet(...))”内部的@Holger注释,你只能保证看到线程所做的更改,期望值”? – Gedrox

+0

是的,我同意这种说法。由于我们不能说失败的线程成功写入,它永远不会发出易失性存储。因此,该线程的写入和连续线程的读取之间没有同步。 –