在尝试了解如何实现SubmissionPublisher
(Java SE 10中的源代码,OpenJDK | docs),在版本9中添加到Java SE的新类的实现之后,我偶然发现了一些VarHandle
以前没有意识到的API调用:
fullFence
,acquireFence
,releaseFence
,loadLoadFence
和storeStoreFence
。
在进行了一些研究之后,尤其是关于内存屏障/栅栏的概念(我以前听说过,是的;但是从未使用过它们,因此对它们的语义非常陌生),我认为我对它们的用途有基本的了解。 。但是,由于我的问题可能是由错误的观念引起的,因此我想确保我一开始就正确:
内存障碍是关于读写操作的重新排序约束。
内存屏障可以分为两大类:单向和双向内存屏障,取决于它们是对读取还是写入或对这两者设置约束。
C ++支持多种内存屏障,但是这些屏障与所提供的屏障不匹配
VarHandle
。然而,一些在可用内存壁垒VarHandle
提供排序的影响是兼容其相应的C ++内存屏障。#fullFence
与...兼容atomic_thread_fence(memory_order_seq_cst)
#acquireFence
与...兼容atomic_thread_fence(memory_order_acquire)
#releaseFence
与...兼容atomic_thread_fence(memory_order_release)
#loadLoadFence
并且#storeStoreFence
没有兼容的C ++计数器部分
“ 兼容 ”一词在这里似乎非常重要,因为在细节上语义明显不同。例如,所有C ++障碍都是双向的,而Java障碍不是必需的。
- 大多数内存屏障也具有同步效果。这些特别取决于其他线程中使用的屏障类型和先前执行的屏障指令。由于障碍指令的全部含义是特定于硬件的,因此我将坚持使用更高级别的(C ++)障碍。在C ++中,例如,改变由之前的释放屏障指令是执行一个线程可见获取屏障指令。
我的假设正确吗?如果是这样,我的问题是:
可用的内存屏障是否
VarHandle
会引起任何类型的内存同步?无论它们是否引起内存同步,重新排序约束在Java中可能有什么用?Java内存模型已经就可变字段,锁或
VarHandle
类似操作的顺序提供了一些非常有力的保证#compareAndSet
。
如果您正在寻找一个示例:前面提到BufferedSubscription
的SubmissionPublisher
(内部链接为的内部类)在第1079行中建立了完整的围栏(功能growAndAdd
;由于链接的网站不支持片段标识符,因此仅需使用CTRL + F )。但是,我不清楚它的用途。
plain -> opaque -> release/acquire -> volatile (sequential consistency)
。