- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我阅读了很多帖子并观看了几个 Youtube 视频 C++ 原子和内存模型(ConCpp 17、14)。
当我阅读Concurrency In Action一书的第 5.3.3 节,RELAXED ORDERING 时,我仍然无法理解作者在他的假设下提供的示例。
It’s not just that the compiler can reorder the instructions. Even if the threads are running the same bit of code, they can disagree on the order of events because of operations in other threads in the absence of explicit ordering constraints, because the different CPU caches and internal buffers can hold different values for the same memory. It’s so important I’ll say it again: threads don’t have to agree on the order of events. Not only do you have to throw out mental models based on interleaving operations, you also have to throw out mental models based on the idea of the compiler or processor reordering the instructions.
假设我们看到的代码没有重新排序。
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<int> z;
void write_x_then_y()
{
x.store(true,std::memory_order_relaxed); // 1
y.store(true,std::memory_order_relaxed); // 2
}
void read_y_then_x()
{
while(!y.load(std::memory_order_relaxed)); // 3
if(x.load(std::memory_order_relaxed)) // 4
++z;
}
int main() {
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0); // 5
}
来自此链接:https://www.developerfusion.com/article/138018/memory-ordering-for-atomic-operations-in-c0x/
为什么 x.load(relaxed)
返回 false
但是y.load(relaxed)
返回 true
?
This time the assert (5) can fire, because the load of x (4) can read false, even though the load of y (3) reads true and the store of x (1) happens-before the store of y (2). x and y are different variables, so there are no ordering guarantees relating to the visibility of values arising from operations on each.
作者得出的结论是 assert 可以触发。所以,z
可以是0
.所以,if(x.load(std::memory_order_relaxed))
: x.load(std::memory_order_relaxed)
是false
.
但无论如何,while(!y.load(std::memory_order_relaxed));
使 y
true
.
如果我们不重新排序 (1) 和 (2) 的代码序列,怎么可能 y
是真的但是x
还是没有存储?
如何理解作者提供的图?
基于 the store of x (1) happens-before the store of y (2)
, 如果 x.store(relaxed)
之前发生 y.store(relaxed)
, x
应该是 true
现在。但是为什么x
还是false
甚至 y
是true
?
最佳答案
您和 friend 都同意 x=false
和 y=false
。有一天,您给他发了一封信,告诉他 x=true
。第二天,您给他发了一封信,告诉他 y=true
。您绝对以正确的顺序向他发送信件。
一段时间后,您的 friend 收到您的一封信,信中说 y=true
。现在您的 friend 对 x
了解多少?他可能已经收到告诉他x=true
的信件。但也许邮政系统暂时丢失了它,他明天就会收到。所以对他来说,x=false
和 x=true
都是当他收到 y=true
信件时的有效可能性。
那么,回到硅世界。线程之间的内 stub 本不能保证来自其他线程的写入以任何特定顺序出现,因此“延迟 x”完全是可能的。所有添加 atomic
和使用 relaxed
所做的都是阻止两个线程在单个变量上竞争成为未定义的行为。它对订购没有任何保证。 这就是强排序的目的。
或者,以更粗略的方式,看看我的 MSPaint 技能:
在这种情况下,表示“x”从第一个线程流向第二个线程的紫色箭头来得太晚,而绿色箭头(y 交叉)发生得很快。
关于c++ - 如何理解 std::memory_order (C++) 中的 RELAXED ORDERING,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55680665/
这是一个关于 std::memory_order 的问题C++11 中的规则,当涉及到三个线程时。比如说,一个线程 producer 保存一个值并设置一个标志。然后,另一个线程 relay 在设置另一
我有以下 C++ 2011 代码: std::atomic x, y; std::atomic z; void f() { x.store(true, std::memory_order_rel
我读了一章,我不太喜欢它。我仍然不清楚每个内存顺序之间的区别是什么。这是我目前的猜测,在阅读了更简单的 http://en.cppreference.com/w/cpp/atomic/memory_o
据我所知,std::memory_order 枚举提供内存栅栏,但我需要确定每个 std::memory_order 枚举元素提供的栅栏。下面我按照我对每个 std::memory_order 枚举元
#include std::atomic val{1}; const auto my_order = std::memory_order_relaxed; // const lvalue int m
在像 std::atomic::compare_exchange 这样的函数中,有像 std::memory_order_release、std::memory_order_relaxed 这样的运行
作为我之前 question 的跟进, atomic类使用 memory_order 指定大多数操作范围。与栅栏相反,此内存顺序仅影响其操作的原子。据推测,通过使用几个这样的原子,您可以构建一个并发算
您能否给出一个真实世界的例子,其中出于某种原因使用了 std::atomic::compare_exchange 的两个 memory_order 参数版本(因此一个 memory_order 参数版
std::atomic_flag 有 2 个具有这些默认 std::memory_order 的函数: void clear(std::memory_order order = std::memory
std::atomic 函数,例如 store 和 load 采用 std::memory_order 参数。参数可以在运行时确定,就像任何其他函数参数一样。但是,实际值可能会影响编译期间代码的优化。
谁能解释一下 std::memory_order 是什么?用简单的英语,以及如何将它们与 std::atomic<> 一起使用? 我在这里找到了引用资料和几个例子,但根本不明白。 http://en.
根据cppreference,在C++20中有wait , notify_one , notify_all在std::atomic 。看起来他们做 std::atomic可用作futex。 我问为什么
我阅读了很多帖子并观看了几个 Youtube 视频 C++ 原子和内存模型(ConCpp 17、14)。 当我阅读Concurrency In Action一书的第 5.3.3 节,RELAXED O
似乎与成员函数不同,您无法指定要使用的 memory_order,因此可能最终使用了一些“默认”。 最佳答案 根据 C++ 标准 (§29.7/35),使用非原子调用原子类型 A 的 operator
C++ 标准中滥用 std::memory_order::relaxed 的示例之一: std::atomic x{0}; int a[] = {1,2}; std::for_each(std::ex
我是一名优秀的程序员,十分优秀!