c++ - 为什么这个获取和释放内存栅栏没有给出一致的值?

标签 c++ multithreading c++11 concurrency memory-barriers

我只是在探索获取和释放内存栅栏的使用,不明白为什么我有时会将值输出设为零,而不是一直将值设为 2

我多次运行该程序,并假设释放屏障之前的原子存储和获取屏障之后的原子加载将确保值始终同步

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int>x;



void write()
{


    x.store(2,std::memory_order_relaxed);

    std::atomic_thread_fence(std::memory_order_release);



}

void read()
{

    std::atomic_thread_fence(std::memory_order_acquire);

    // THIS DOES NOT GIVE THE EXPECTED VALUE OF 2 SOMETIMES
    std::cout<<x.load(std::memory_order_relaxed)<<std::endl; 

}

int main()
{

std::thread t1(write);
std::thread t2(read);
t1.join();
t2.join();
return 0;
}

原子变量 x 有时给出 0 的值

最佳答案

我认为您误解了栅栏的用途。 Fences 仅在单个执行线程中为编译器和处理器强制执行特定的内存操作顺序。您的获取栅栏不会神奇地让线程等待直到另一个线程执行释放。

一些文献将描述一个线程中的释放操作与另一个线程中的后续获取操作“同步”。这样做的关键是获取操作是后续操作(即获取是在发布“之后”排序的)。如果释放操作在您的获取操作之后排序,则写入和读取操作之间没有同步关系。

您的代码无法始终如一地返回您所期望的原因是因为线程交错有时先写后读,有时先读后写。

如果你想保证线程 t2 读取线程 t1 发布的值 2,你将不得不强制 t2 等待发布发生。教科书示例几乎总是使用一个保护变量来通知 t2 数据已准备好使用。

我建议您在 Preshing on Programming 的 The Synchronizes-With Relation 上阅读一篇关于发布和获取语义以及同步关系的非常好的博客文章。 .

关于c++ - 为什么这个获取和释放内存栅栏没有给出一致的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56386448/

相关文章:

sql - 线程安全的sql事务,如何在事务期间锁定特定行?

java - 如何让一个java线程等待另一个线程的结果?

c++ - 声明继承的模板化对象并将它们推回 vector - 优雅的方式?

c++ - 如何访问OpenCV图像的所有 channel

java - 返回 int 是 java 中的原子操作吗?

c++ - 哪种类型特征表明该类型是 memcpy 可分配的? (元组,对)

c++ - 赋值运算符

c++ - 最小二乘的 SparseQR

c++ - 在 libXML sax 解析器(C++)中获取属性值的正确方法是什么?

c++ - ImageMagick- eclipse