我在各种地方(论坛等)都看到了这个参数,它帮助高并发服务器的常见答案。尽管如此,我还是找不到来自 sun 的官方文档来解释它的作用。另外,它是在 Java 6 中添加的还是在 Java 5 中存在?
(顺便说一句,很多热点VM参数的好地方就是这个页面)
更新: Java 5 不使用此参数启动。
我在各种地方(论坛等)都看到了这个参数,它帮助高并发服务器的常见答案。尽管如此,我还是找不到来自 sun 的官方文档来解释它的作用。另外,它是在 Java 6 中添加的还是在 Java 5 中存在?
(顺便说一句,很多热点VM参数的好地方就是这个页面)
更新: Java 5 不使用此参数启动。
为了优化性能,JVM 在跨多个处理器同步时在代码中使用“伪内存屏障”作为隔离指令。可以恢复到“真正的”内存屏障指令,但这会对性能产生明显(和不良)的影响。
的使用-XX:+UseMembar
会导致 VM 恢复为真正的内存屏障指令。这个参数原本是打算作为新伪屏障逻辑的验证机制暂时存在的,结果发现新的伪内存屏障代码引入了一些同步问题。我相信这些现在已经修复,但在修复之前,解决这些问题的可接受方法是使用恢复标志。
该错误是在 1.5 中引入的,我相信该标志存在于 1.5 和 1.6 中。
我从各种邮件列表和 JVM 错误中对此进行了谷歌分析:
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
我不同意奶油鸡的回答。这个页面 http://www.md.pp.ru/~eu/jdk6options.html 说这个标志会导致内存屏障被发出然后线程改变它的状态(例如从 RUNNABLE 到 WAITING 或 BLOCKED)。
UseMembar 以严格的方式确定是否使用 membar 指令,强制所有内存操作完成后再继续。
它基本上阻止了处理器的延迟内存处理优化与处理的代码混淆。
这通常会减慢速度,并且在现代 VM 上对于绝大多数代码来说都不是必需的。
有时您会遇到代码应该是线程安全的问题,但不是因为缺少 membar 指令使用。在这些情况下,您可以打开它以使此类代码正常工作,而无需切换到单线程或弄乱代码的顺序以防止出现问题。
JVM 通常擅长检测会导致问题的代码,并插入一个 membar 或进行 JIT 代码重新排列优化,以便为完成内存操作提供时间。事实上,在我对该主题的网络搜索中,我只找到了一个错误示例,并且在热点 JVM 的 Oracle 和 OpenJRE 版本的最新版本中都已修复。
请注意,对于 ARM 架构,此选项仍默认为打开,因为尚未应用替代优化(称为伪内存条优化),因此如果没有内存条指令,它可能会出现非常多的错误。