Java 内存模型清楚地说明了关于线程如何通过内存进行交互的假设和不可以假设。例如,如果一个线程在没有适当同步的情况下将新值写入字段,则不能保证其他线程可以观察到新值。然而,在实践中,尽管同步不充分,其他线程仍可能读取新值,这取决于写入和读取之间的时间、硬件架构等。
这可能导致难以发现且难以重现的错误。因此,在超出Java 内存模型保证的线程之间绝对没有内存同步的最坏情况 JVM 上运行 Java 应用程序可能很有用。这种最坏情况的 JVM 实现是否存在?
Java 内存模型清楚地说明了关于线程如何通过内存进行交互的假设和不可以假设。例如,如果一个线程在没有适当同步的情况下将新值写入字段,则不能保证其他线程可以观察到新值。然而,在实践中,尽管同步不充分,其他线程仍可能读取新值,这取决于写入和读取之间的时间、硬件架构等。
这可能导致难以发现且难以重现的错误。因此,在超出Java 内存模型保证的线程之间绝对没有内存同步的最坏情况 JVM 上运行 Java 应用程序可能很有用。这种最坏情况的 JVM 实现是否存在?
您可以尝试使用Terracotta来集群您的程序。不正确的同步是令人难以置信的无情(即使集群中只有一个节点也会变得很明显)。这是一个很好的问题:我经常想要这种能力——我很惊讶标准 JRE 中没有开关-XXJMMExtreme
Terracotta 是开源的,基本产品免费。
这可能会有所帮助:http: //javapathfinder.sourceforge.net/
我不知道有任何 VM 可以一直保证最坏情况的行为,这似乎是您所要求的。您所描述的情况可能发生在 Sun VM(以及许多其他 VM)上,但这只是由于缓存问题。我不熟悉一直故意这样做的虚拟机。
有很多方法可以触发并发错误。
对于最坏情况下的 JVM,请尝试使用手机。(您的应用程序可能根本无法运行);)
同步错误通常很难重现,因为它们取决于不同线程之间的微妙计时,因此实际上尝试“只运行您的程序”的任何实现都不会总是“最糟糕的”。如果您只执行一次这些指令,则无法重现两个线程可以交错其指令的一种以上不同的方式。在一次运行中测试所有这些组合甚至更不可能。其他海报之一建议使用 Java Pathfinder,这听起来是个好主意 - 但请注意,它是一个多次运行相同代码的应用程序,因此您不能真正将其视为另一个 JVM 实现。
另一个实用技巧是尝试在尽可能多的不同 JVM 上运行应用程序。尝试不同的供应商,同一供应商的不同版本,不同的 CPU 架构等等。几年前,我曾在 Sun 的 JVM 上在 Xeon CPU 上开发、测试和运行一个高度多线程的应用程序,它运行良好。有一次,我尝试在 IBM 的 J9 Java Virtual Machine on POWER 架构上运行它,第一次尝试时,大约 2/3 的测试由于同步错误而失败。因此,在不同环境中进行测试可以很好地暴露隐藏的同步问题。