什么是Java的-XX:+ UseMembar参数

时间:2009-07-13 15:16:45

标签: java concurrency jvm jvm-arguments

我在各种地方(论坛等)看到这个参数,并且它有助于高度并发的服务器。尽管如此,我还是找不到太阳的官方文件来解释它的作用。它是在Java 6中添加还是在Java 5中存在?

(BTW,许多热点VM参数的好地方是this page

更新: Java 5无法使用此参数启动。

4 个答案:

答案 0 :(得分:12)

为了优化性能,JVM在代码中使用“伪内存屏障”,在跨多个处理器进行同步时充当屏蔽指令。可以恢复到“真正的”内存屏障指令,但这会对性能产生明显(和不良)的影响。

使用-XX:+UseMembar会导致VM恢复为真正的内存屏障指令。该参数最初旨在作为新伪屏障逻辑的验证机制暂时存在,但事实证明新的伪存储器屏障代码引入了一些同步问题。我相信这些现在已经修复,但在它们出现之前,解决这些问题的可接受方法是使用恢复的标志。

该错误是在1.5中引入的,我相信该标志存在于1.5和1.6中。

我已经通过各种邮件列表和JVM错误进行了google-fu'ed:

答案 1 :(得分:4)

butterchicken只解释了故事的一半,我想向kmatveev的答案增加更多细节。是的,该选项用于线程状态更改,并且(伪)内存屏障用于确保从其他线程(尤其是VM线程)可以看到更改。 OpenJDK6中使用的线程状态如下:

//  _thread_new         : Just started, but not executed init. code yet (most likely still in OS init code)
//  _thread_in_native   : In native code. This is a safepoint region, since all oops will be in jobject handles
//  _thread_in_vm       : Executing in the vm
//  _thread_in_Java     : Executing either interpreted or compiled Java code (or could be in a stub)
...
 _thread_blocked           = 10, // blocked in vm   

如果没有UseMembar选项,在Linux中,Hotspot使用内存序列化页面而不是内存屏障指令。每当发生线程状态转换时,线程就会使用易失性指针写入内存序列化页面中的内存地址。当VM线程需要查看所有线程的最新状态时,VM会将内存序列化页面的保护位更改为只读,然后将其恢复为读/写以序列化状态更改。更详细的机制在以下页面中介绍:

http://home.comcast.net/~pjbishop/Dave/Asymmetric-Dekker-Synchronization.txt

答案 2 :(得分:2)

UseMembar确定是否以严格的方式使用membar指令,强制所有内存操作在继续之前完成。

它基本上会停止处理器的延迟内存处理优化,以免处理代码。

这通常会减慢速度,对于绝大多数代码来说,现代虚拟机并不是必需的。

有时你遇到的问题是代码应该是线程安全的但不是因为缺少使用membar指令。在这些情况下,您可以启用此功能,以使此类代码无需切换到单线程或使用代码排序来防止此问题。

JVM通常擅长检测会导致问题的代码,并插入一个membar或执行JIT代码重新排列优化,以便为内存操作完成提供时间。事实上,在我对该主题的网络搜索中,我只找到了一个bug的例子,并且在热点JVM的Oracle和OpenJRE版本的最新版本中修复了它。

请注意,对于ARM体系结构,此选项仍然默认为on,因为尚未应用备用优化(称为psuedo-membar优化),因此在没有membar指令的情况下它会非常错误。

答案 3 :(得分:1)

我不同意butterchicken的回答。这一页 http://www.md.pp.ru/~eu/jdk6options.html 说这个标志会导致发出内存障碍然后线程改变它的状态(例如从RUNNABLE到WAITING或者BLOCKED)。