相关疑难解决方法(0)

Java 中的内存栅栏是做什么用的?

在试图了解SubmissionPublisherJava SE 10 中的源代码,OpenJDK | docs),在版本 9 中添加到 Java SE 的新类是如何实现的,我偶然发现了一些VarHandle我以前不知道的API 调用:

fullFenceacquireFencereleaseFenceloadLoadFencestoreStoreFence

在做了一些研究之后,特别是关于内存屏障/栅栏的概念(我以前听说过它们,是的;但从未使用过它们,因此对它们的语义非常不熟悉),我想我对它们的用途有了基本的了解. 尽管如此,由于我的问题可能源于误解,我想确保我首先做对了:

  1. 内存屏障是关于读写操作的重新排序约束。

  2. 内存屏障可以分为两大类:单向和双向内存屏障,这取决于它们是否对读取或写入或两者都设置了约束。

  3. 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 的屏障不是(必然)。

  1. 大多数内存屏障也具有同步效应。那些特别依赖于其他线程中使用的屏障类型和先前执行的屏障指令。由于屏障指令的全部含义是特定于硬件的,因此我将坚持使用更高级别的 (C++) 屏障。例如,在 C++ 中,在释放屏障指令之前所做的更改对于执行获取屏障指令的线程是可见的。

我的假设正确吗?如果是这样,我产生的问题是:

  1. 可用的内存屏障是否VarHandle会导致任何类型的内存同步? …

java concurrency memory-model java-memory-model memory-barriers

21
推荐指数
1
解决办法
770
查看次数

内存顺序在 C11 中消耗使用量

我读过有关携带依赖关系和依赖关系排序之前,在其定义中使用一个5.1.2.4(p16)

在以下情况下,评估A在评估之前是依赖顺序的B

A对原子对象执行释放操作M,并在另一个线程中B执行消耗操作M并读取以 为首的释放序列中的任何副作用写入的值A,或

— 对于某些求值XA之前是依存顺序XX带有对 的依存关系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)

c multithreading c11 stdatomic

4
推荐指数
1
解决办法
896
查看次数

如何理解Java语言规范中的易失性示例?

我认为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 jvm java-memory-model language-lawyer

4
推荐指数
1
解决办法
144
查看次数

compareAndExchange 与 compareAndExchangeAcquire 有什么区别

这是 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

在此处输入图片说明

java concurrency java-14

0
推荐指数
1
解决办法
292
查看次数