问题标签 [memory-fences]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
801 浏览

c++11 - C11 和 C++11 原子:获取-释放语义和内存屏障

我正在使用 C11* atomics 来管理几个线程之间的状态枚举。代码类似于以下内容:

这组装(对于 ARM Cortex-M4)到:

为什么要在发布之前和获取之后放置围栏?我的心智模型假设在释放之后(将要存储的变量和所有其他存储“传播”到其他线程)和获取之前(从其他线程接收所有先前的存储)之后放置障碍。


*虽然这个特定示例是在 C11 中给出的,但在 C++11 中的情况是相同的,因为在内存排序方面,两者共享相同的概念(甚至相同的枚举)。gccg++在这种情况下发出相同的机器代码。请参阅http://en.cppreference.com/w/c/atomic/memory_orderhttp://en.cppreference.com/w/cpp/atomic/memory_order

0 投票
2 回答
55 浏览

multithreading - 使用栅栏确保其他线程的数据更新可见性

我有两个问题 - 考虑两个线程,一个对共享数据进行更改,另一个对共享数据进行操作。两个线程在对数据进行任何操作之前都会获取一个互斥锁。

如何保证对数据进行操作的线程总是看到第一个线程所做的更改?是否需要一组获取/释放栅栏,或者线程是否通过使用互斥锁隐式同步?如果我不使用互斥锁(但要确保独占访问)怎么办?

并且:在没有交错/后续原子操作的情况下,栅栏实际上会做任何事情吗(例如,将标志存储在 atomic_bool 中,发出“准备就绪”或其他信号)?

这是一个用例:

0 投票
1 回答
341 浏览

c++ - 栅栏在 C++ 中是如何工作的

我一直在努力理解栅栏实际上是如何强制代码同步的。

例如,假设我有这个代码

因为释放栅栏之后是原子存储操作,而获取栅栏之前是原子加载,所以一切都按预期同步,并且断言不会触发

但如果 y 不是这样的原子变量

然后,我听说,可能会有一场数据竞赛。但这是为什么呢?为什么释放栅栏后必须跟原子存储,而获取栅栏前必须有原子加载才能使代码正确同步?

如果有人可以提供数据竞争导致断言触发的执行场景,我也将不胜感激

0 投票
1 回答
132 浏览

c - 可以使用 C11 栅栏来推断来自其他线程的写入吗?

Adve 和 Gharachorloo 的报告在图 4b 中提供了以下程序示例,该程序在没有顺序一致性的情况下表现出意外行为:

在此处输入图像描述

我的问题是是否有可能,仅使用 C11 栅栏和memory_order_relaxed加载和存储,以确保 register1,如果写入,将被写入值 1。这在抽象中可能难以保证的原因是 P1,P2,并且 P3 可能位于病态 NUMA 网络中的不同点,其​​属性是 P2 在 P3 之前看到 P1 的写入,但不知何故 P3 很快看到 P2 的写入。对于 C11 规范,这可能难以保证的原因是 P1 对 A 的写入和 P2 对 A 的读取不会彼此同步,因此规范的第 5.1.2.4.26 段将导致未定义的行为. 可能我可以通过轻松的原子获取/存储来回避未定义的行为,但我仍然不知道如何对 P3 看到的顺序进行传递推理。

下面是一个试图解决栅栏问题的 MWE,但我不确定它是否正确。我特别担心释放栅栏不够好,因为它不会刷新 p1 的存储缓冲区,只会刷新 p2 的。但是,如果您可以争辩说仅基于 C11 标准断言将永远不会失败,它将回答我的问题(与人们可能拥有的有关特定编译器和体系结构的其他一些信息相反)。

0 投票
1 回答
342 浏览

java - 同步块是否会触发数组的完整内存围栏?

我对在 Java 中的线程之间安全地共享数组感到困惑,特别是内存栅栏和关键字synchronized.

此问答很有帮助,但不能回答我的所有问题:Java 数组:同步 + 原子*,还是同步就足够了?

以下是演示该问题的示例代码。假设有一个填充SharedTablevia 方法的工作线程池add(...)。在所有工作线程完成后,最后一个线程读取并保存数据。

演示问题的示例代码:

上面的示例代码也可以使用 来实现Atomic*Array,它充当“易失性值/引用的数组”。

  1. SharedTable线程安全(和缓存一致)吗?
  2. (很多?SharedTable)效率更高,因为只需要一个内存栅栏,而SharedTable2每次调用都调用一个内存栅栏Atomic*Array.set(...)

如果有帮助,我将在 64 位 x86 硬件(Windows 和 Linux)上使用 Java 8。

0 投票
1 回答
171 浏览

java - 如何在不使用 sun.misc.Unsafe 的情况下触发完整的内存围栏?

我有兴趣在不使用sun.misc.Unsafe.

以下 Java 代码是否会触发完整的内存围栏?

下面的 Java 代码是否也会触发完整的内存围栏?

0 投票
1 回答
662 浏览

c++ - OpenMP 原子和非原子读/写在 x86_64 上产生相同的指令

根据 OpenMP 规范 (v4.0),以下程序包含由于不同步的读/写导致的可能的数据竞争i

我想到的可能解决方案在代码中显示为注释:

  1. 保护写入和读取iwith #pragma omp atomic write/read
  2. 保护写入和读取iwith #pragma omp atomic write/read seq_cst
  3. 使用std::atomic<int>而不是int作为i.

以下是 x86_64 上编译器生成的指令(-O2在所有情况下都有):

我想知道为什么 GNU/clang 编译器不为#pragma omp atomic写入生成任何特殊指令。我希望与 for 类似的说明std::atomic,即,要么MOV+MFENCE要么XCHG。有什么解释吗?

更新

g++ 5.3.0MFENCE#pragma omp atomic write seq_cst. 这是正确的行为,我相信。没有seq_cst,它会产生普通的MOV,这对于非 SC 原子性来说已经足够了。

我的 Makefile 中有一个错误,g++ 4.9.2MFENCE也为 CS atomic write 生成。对不起,伙计们。

Clang 3.5.0 没有实现 OpenMP SC 原子,感谢 Hristo Iliev 指出这一点。

0 投票
3 回答
172 浏览

java - 我应该使用什么作为集合的内存屏障?

假设我有一个 Java ArrayList,它显然不能是一个volatile变量(volatile在某种意义上:它的所有内部变量都是volatile),并且想在第二个线程中查看它的最新状态,因为我可以确定第二个线程是在第一个线程结束(可能已修改ArrayList实例的第一个线程)。

使用内存屏障应该很容易。但是我怎样才能构造这样一个影响ArrayList实例的所有内部成员变量/状态的内存屏障呢?我知道同步是一种选择,但我不知道我应该在哪个对象上同步才能达到预期的效果。

有没有关于这个问题的官方参考,定义一个最佳实践?

在我看来,实现内存屏障最直接的方法是调用类似fullFence(). 但似乎这不是推荐的方式;-)

0 投票
2 回答
670 浏览

c++ - One reader one writer, int or atomic_int

I know this isn't a new issue, but I got confused after reading about c++11 memory fences;

If I have one reader thread and one writer thread.
Can I use an ordinary int?

Is this behavior is undefined?
May I get an undefined value in the reader thread?
Or it's like using an std::atomic_uint_fast32_t or std::atomic<int>? So the value will get to the reader thread - eventually.

Does the answer depends on the platform I'm using? (x86 for example), so loading/storing an ordinary int is one CPU instruction?

If both of the behaviors are similar, should I expect the same performance for both of the types?

0 投票
3 回答
498 浏览

c# - 内存屏障是否保证在 C# 中重新读取?

如果我们在 C# 中有以下代码:

MemoryBarriers确保写入指令发生在读取之前。但是,是否保证一个线程的写入被另一个线程上的读取看到?换句话说,是否保证至少一个线程打印1或两个线程都可以打印0

MemoryBarrier我知道在 C# 中已经存在几个与“新鲜度”相关的问题,例如thisthis。但是,它们中的大多数都处理写-释放和读-获取模式。这个问题中发布的代码非常具体地说明在指令保持有序这一事实之上,是否保证读取可以查看写入。