内存栅栏在 Java 中的用途是什么?
在试图理解(OpenJDK 10,Javadoc中的源代码)是如何实现的(在版本9中添加到Java SE中的新类)时,我偶然发现了一些我以前不知道的对VarHandle
的API调用:SubmissionPublisher
fullFence
和。acquireFence
releaseFence
loadLoadFence
storeStoreFence
在做了一些研究之后,特别是关于记忆障碍/栅栏的概念(我以前听说过它们,是的;但从未使用过它们,因此对它们的语义非常不熟悉),我想我对它们的用途有了基本的了解。尽管如此,由于我的问题可能源于误解,我想确保我首先做对了:
-
内存障碍是有关读取和写入操作的重新排序约束。
-
内存屏障可分为两大类:单向和双向内存屏障,具体取决于它们是对读取还是写入或两者都设置约束。
-
C++支持各种内存屏障,但是,这些屏障与 提供的内存屏障不匹配。但是,
VarHandle
中提供的一些内存屏障提供的排序效果与其相应的C++内存屏障兼容。VarHandle
-
#fullFence
兼容于atomic_thread_fence(memory_order_seq_cst)
-
#acquireFence
兼容于atomic_thread_fence(memory_order_acquire)
-
#releaseFence
兼容于atomic_thread_fence(memory_order_release)
-
#loadLoadFence
并且没有兼容的C++计数器部件#storeStoreFence
“兼容”这个词在这里似乎非常重要,因为当涉及到细节时,语义明显不同。例如,所有C++障碍都是双向的,而Java的障碍不是(必然的)。
- 大多数内存屏障也具有同步效果。这些尤其取决于所使用的屏障类型和其他线程中先前执行的屏障指令。由于屏障指令的全部含义是特定于硬件的,因此我将坚持使用更高级别(C++)屏障。例如,在C++中,在发布障碍指令之前所做的更改对于执行获取障碍指令的线程是可见的。
我的假设是否正确?如果是这样,我得出的问题是:
-
中可用的内存屏障是否会导致任何类型的内存同步?
VarHandle
-
无论它们是否会导致内存同步,在Java中重新排序约束可能有什么用处?Java内存模型已经提供了一些关于在涉及易失性字段,锁或类似操作时进行排序的非常强大的保证。
VarHandle
#compareAndSet
如果你正在寻找一个例子:前面提到的,一个内部类(上面链接的源代码),在第1079行中建立了一个完整的围栏,函数。但是,我不清楚它的作用。BufferedSubscription
SubmissionPublisher
growAndAdd