Java中的多线程状态可见性:有没有办法将JVM变成最坏的情况?

Geo*_*met 13 java concurrency jvm jvm-arguments race-condition

假设我们的代码有2个线程(A和B)在某个地方引用了这个类的同一个实例:

public class MyValueHolder {

    private int value = 1;

    // ... getter and setter

}
Run Code Online (Sandbox Code Playgroud)

当线程A执行时myValueHolder.setValue(7),无法保证线程B将读取该值:myValueHolder.getValue()理论上 - 可以1永远返回.

然而,在实践中,硬件迟早会清除二级缓存,因此线程B将7迟早读取(通常更早).

是否有任何方法可以使JVM模拟最坏情况下它1为线程B永远返回的情况?在这些情况下使用我们现有的测试测试我们的多线程代码非常有用.

Ale*_*lev 27

jcstress维护者在这里.有多种方法可以回答这个问题.

  1. 最简单的解决方案是将getter包装在循环中,让JIT将其提升.这允许非易失性字段读取,并通过编译器优化模拟可见性故障.
  2. 更复杂的技巧涉及获取OpenJDK的调试版本,并使用-XX:+StressLCM -XX:+StressGCM,有效地执行指令调度模糊测试.有问题的负载会漂浮到您可以通过产品的常规测试检测到的地方.
  3. 我不确定是否有实用的硬件保持写入值足够长的不透明缓存一致性,但使用jcstress构建测试用例有点容易.你必须记住,(1)中的优化也可能发生,所以我们需要采用一种技巧来防止这种情况.我认为有些事情是这样应该工作.