在试图了解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 的屏障不是(必然)。
我的假设正确吗?如果是这样,我产生的问题是:
可用的内存屏障是否VarHandle会导致任何类型的内存同步? …
java concurrency memory-model java-memory-model memory-barriers
我读过有关携带依赖关系和依赖关系排序之前,在其定义中使用一个5.1.2.4(p16):
在以下情况下,评估
A在评估之前是依赖顺序的B:—
A对原子对象执行释放操作M,并在另一个线程中B执行消耗操作M并读取以 为首的释放序列中的任何副作用写入的值A,或— 对于某些求值
X,A之前是依存顺序X并X带有对 的依存关系B。
所以我试图制作一个可能有用的例子。就这个:
static _Atomic int i;
void *produce(void *ptr){
int int_value = *((int *) ptr);
atomic_store_explicit(&i, int_value, memory_order_release);
return NULL;
}
void *consume(void *ignored){
int int_value = atomic_load_explicit(&i, memory_order_consume);
int new_int_value = int_value + 42;
printf("Consumed = %d\n", new_int_value);
}
int main(int …Run Code Online (Sandbox Code Playgroud) 我认为Java规范中volatile的示例有些错误。
在8.3.1.4中。挥发性字段,它说
class Test {
static int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
Run Code Online (Sandbox Code Playgroud)
...然后方法二可能偶尔会为j打印一个大于i的值,因为该示例不包含同步,并且在第17.4节中解释的规则下,i和j的共享值可能会更新为订购。
我认为,即使这些更新是按顺序进行的,方法二仍可能看到j大于i,因为System.out.println("i=" + i + " j=" + j)它不是原子的,并且i在j之前被读取。
方法二是一样的
read i
read j
Run Code Online (Sandbox Code Playgroud)
所以有可能
read i
i++
j++
read j
Run Code Online (Sandbox Code Playgroud)
在这种情况下,方法二看到j的值大于i,但是更新不会乱序。
因此,乱序并不是看到j> i的唯一原因
应该是System.out.println("j=" + j + " i=" + i);吗?
这次故障是看到j> i的唯一原因
这是 Java 库中的一个片段:
public final boolean compareAndExchangeAcquire(boolean expectedValue, boolean newValue) {
return (int)VALUE.compareAndExchangeAcquire(this,
(expectedValue ? 1 : 0),
(newValue ? 1 : 0)) != 0;
}
Run Code Online (Sandbox Code Playgroud)
它来自AtomicBoolean课堂。演员怎么能int返回一个boolean?
我的主要问题:compareAndExchangevs之间有什么区别compareAndExchangeAcquire?
通俗地说:在申请之前xxxAcquire和之后写的语句xxxRelease可以自由重新排序xxx。