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

13

我在各种地方(论坛等)看到这个参数,并且常见回答是它有助于高并发服务器。然而,我找不到来自sun官方的解释说明它的作用。此外,它是在Java 6中添加的还是在Java 5中就已经存在了?

(顺便说一句,许多Hotspot VM参数的好地方在此页面

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


1
顺便提一下:-XX选项并非官方支持,未来的版本可能会在没有通知的情况下移除。 - Rastislav Komara
1
@Rastislav 是的,但在许多情况下你需要使用它们... - David Rabinowitz
4个回答

13
为了优化性能,JVM在代码中使用了一个“伪内存屏障”来作为在多个处理器之间进行同步时的围栏指令。可以将其恢复为“真正的”内存屏障指令,但这可能会对性能产生明显(且不好的)影响。
使用-XX:+UseMembar参数会导致VM恢复为真正的内存屏障指令。这个参数最初是作为新的伪屏障逻辑的验证机制而存在的,但事实证明,新的伪内存屏障代码引入了一些同步问题。我相信这些问题现在已经修复了,但在修复之前,解决这些问题的可接受方法是使用恢复的标志。
这个错误是在1.5版本引入的,我相信这个标志存在于1.5和1.6版本中。
我从各种邮件列表和JVM错误中搜索到了这个信息。

另请参见http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370:在新的CPU和具有此错误的VM上,您可能会遇到非常奇怪的同步问题(在6u18中已修复)。 - ankon

5
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
我不同意butterchicken的回答。这个页面http://www.md.pp.ru/~eu/jdk6options.html说,这个标志会导致内存屏障在线程改变状态时被发出(例如从RUNNABLE到WAITING或BLOCKED)。

它基本上改变了任何线程状态的变化行为。因此,它适用于各种情况。ButterChicken太狭窄了,只指定了membar的较不常见和较不侵入性的用法之一。最具侵入性的是在序列化线程时以及以任何其他方式更改线程状态以进行立即执行时,而不是在跳转CPU时(这会更改线程状态,但发出membar不会有侵入性)。 - Robert Wm Ruedisueli

2

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

它基本上阻止了处理器的延迟内存处理优化对代码的干扰。

这通常会减慢速度,并且对于现代VM中的绝大多数代码来说是不必要的。

偶尔会遇到应该是线程安全的代码却因为缺乏membar指令而不是线程安全的情况。在这些情况下,您可以打开此选项,使此类代码正常工作,而无需切换到单线程或更改代码的顺序以防止出现问题。

JVM通常很擅长检测可能导致问题的代码,并插入membar或进行JIT代码重新排列优化,以提供时间让内存操作完成。实际上,在我进行的网络搜索中,我只发现了一个错误示例,并且它已在Oracle和OpenJRE版本的hotspot JVM的最新版本中得到修复。

需要注意的是,对于ARM架构,此选项仍然默认打开,因为尚未应用替代优化(称为伪membar优化),因此没有membar指令可能会非常有bug。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接