如何防止JVM重新排序语句

时间:2014-03-04 17:30:42

标签: java concurrency jvm

有没有办法确保在doB之前执行doA?我想到的一件事是将每个语句包装在同步块中。

object1.doA();
object2.doB();

对volatile变量的方法调用是否作为volatile写入?

编辑 - 我真正需要的是让其他线程在doB之前看到doA的效果。

2 个答案:

答案 0 :(得分:2)

这些语句不会从执行该段代码的线程的角度重新排序(它们可能在实践中重新排序,但只有当重新排序从该线程的角度来看没有效果时)。

然而,在看到doB的结果之前,另一个主题可能会看到doA的结果。如果这是一个问题,您应该锁定代码以使其成为原子,例如使用synchronized块。

请注意,使用两个synchronized块并没有太大成效 - 特别是JVM很可能会将它们合并为一个(假设它们使用相同的监视器,但如果它们没有,那么你赢了不一定能实现原子性。

答案 1 :(得分:2)

这完全取决于您观察来自doA()doB()的来电效果的位置。

  • 如果您观察到与执行调用相同的线程的影响,那么您可以保证看到它们没有重新排序。不允许重新排序来更改单线程行为。如果写的代码表示在doA()之前调用了doB(),那么这就是线程将要观察的内容......如果它正在查找。简而言之,没什么惊喜。

  • 如果您观察到来自不同线程的影响,则保证该线程能够观察到与同步点处的单线程情况一致的状态。但是,如果一个线程试图观察另一个线程的动作而没有正确的同步,那么它可以观察重新排序的效果。

所以......

  

如何防止JVM重新排序语句

实际上,我认为你不能。但是,如果您正确编写(多线程)应用程序,它将无法观察重新排序的影响。如果它无法观察到效果,如果有或没有重新排序,它对行为没有任何影响。

  

对volatile变量的方法调用是否充当易失性写入?

没有

调用本身没有特定的同步行为,但它们之前是易失性读取(自然)。

  

...我真正需要的是让其他线程在doB之前看到doA的效果。

然后必须编写代码,以便在访问由相应调用更改的状态时进行适当的同步。从技术上讲,需要在一个线程上的写入与其他线程上的后续读取之间进行适当的“先发生”排序...对于受方法调用影响的所有状态。

没有魔力。没有捷径。只是正确写同步。