Multithreading C11/C++;11记忆模型获取、释放、放松细节
我对C++11/C11内存模型有一些疑问,我想知道是否有人可以澄清。这些是关于模型/抽象机器的问题,而不是关于任何真正的架构Multithreading C11/C++;11记忆模型获取、释放、放松细节,multithreading,c++11,c11,memory-barriers,abstract-machine,Multithreading,C++11,C11,Memory Barriers,Abstract Machine,我对C++11/C11内存模型有一些疑问,我想知道是否有人可以澄清。这些是关于模型/抽象机器的问题,而不是关于任何真正的架构 获取/释放效果是否保证从一个线程“级联”到下一个线程 下面是我的意思的伪代码示例(假设所有变量都以0开头) 线程3的acquire与线程2的release同步,这发生在线程2的acquire与线程1的release同步之后。因此,线程3保证看到线程1设置为x的值,对吗?或者我们需要在这里使用seq cst来保证断言不会触发吗?我觉得获得/释放就足够了,但我找不到任何简单
int* get_data() {...}
void use_data(int* buf) {...}
int* global_ptr = nullptr;
[Thread 1]
int* buf = get_data();
super_duper_memory_fence();
store_relaxed(global_ptr, buf);
[Thread 2]
int* buf = nullptr;
while ((buf = load_relaxed(global_ptr)) == nullptr);
use_data(buf);
是否有任何类型的操作可以放在“超级复制器内存围栏”中,以保证在use\u data获得指针时,缓冲区中的数据也可见?我的理解是,没有一种可移植的方法可以做到这一点,线程2必须有一个匹配的围栏或其他原子操作,以确保它接收写入缓冲区的写入,而不仅仅是指针值。这是正确的吗
线程3的acquire与线程2的release同步,这发生在线程2的acquire与线程1的release同步之后。因此,线程3保证看到线程1设置为x的值,对吗
是的,这是正确的。获取/释放操作建立与同步的关系,即,store\u release(a)
与load\u获取(a)
同步,store\u release(b)
与load\u acquire(b)
同步。而load\u acquire(a)
在store\u release(b)
之前被排序。synchronize with和sequenced before都是“发生在之前”定义的一部分,并且“发生在之前”关系是可传递的。因此,store\u released(x,1)
发生在load\u released(x)
之前
我认为,根据标准,必须始终存在一对非松弛原子操作,每个线程中一个,才能保证任何类型的内存顺序,这是对的吗
这个问题有点过于宽泛,但总的来说,我倾向于说“是”。通常,在对某些(非原子的)共享数据进行操作时,必须确保存在适当的“发生在前”关系。如果一个线程写入某个共享数据,而另一个线程应该读取该数据,则必须确保写入发生在读取之前。实现这一点有不同的方法——具有正确内存顺序的原子只是一种方法(尽管有人可能认为几乎所有其他方法(如std::mutex
)也可以归结为原子操作)
围栏还必须与其他围栏或原子操作相结合。如果super\u duper\u memory\u fence()
是一个std::atomic\u thread\u fence(std::memory\u order\u release)
并且在调用use\u data
之前放置另一个std::atomic\u thread\u fence(std::memory\u order\u acquire)
,则您的示例将起作用
关于更多细节,我可以推荐我与他人合著的这篇论文:
线程3的acquire与线程2的release同步,这发生在线程2的acquire与线程1的release同步之后。因此,线程3保证看到线程1设置为x的值,对吗
是的,这是正确的。获取/释放操作建立与同步的关系,即,store\u release(a)
与load\u获取(a)
同步,store\u release(b)
与load\u acquire(b)
同步。而load\u acquire(a)
在store\u release(b)
之前被排序。与b同步并按顺序排列
int* get_data() {...}
void use_data(int* buf) {...}
int* global_ptr = nullptr;
[Thread 1]
int* buf = get_data();
super_duper_memory_fence();
store_relaxed(global_ptr, buf);
[Thread 2]
int* buf = nullptr;
while ((buf = load_relaxed(global_ptr)) == nullptr);
use_data(buf);