c++ - 如果在互斥锁下没有修改共享原子变量,则无法正确发布

标签 c++ c++11

我正在阅读 http://en.cppreference.com/w/cpp/thread/condition_variable 上有关 std::condition_variable 的信息我不明白这一点:

Even if the shared variable is atomic, it must be modified under the mutex in order to correctly publish the modification to the waiting thread.

如果共享原子变量没有在互斥锁下修改,为什么不能正确发布?如何理解这句话?

在另一页http://en.cppreference.com/w/cpp/atomic/atomic有一个陈述似乎与第一个陈述相矛盾:

If one thread writes to an atomic object while another thread reads from it, the behavior is well-defined (see memory model for details on data races)

最佳答案

考虑这个例子:

std::atomic_bool proceed(false);
std::mutex m;
std::condition_variable cv;

std::thread t([&m,&cv,&proceed]()
{
    {
        std::unique_lock<std::mutex> l(m);
        while(!proceed) {
            hardWork();
            cv.wait(l);
        }
    }
});

proceed = true;
cv.notify_one();
t.join();

这里原子共享数据 proceed 被修改而不使用互斥体,之后通知被发送到条件变量。但是有可能在发送通知的那一刻,线程 t 并没有等待 cv:而是在 hardWork() 在此之前检查了 proceed 并发现它是错误的。错过了通知。当 t 完成 hardWork 时,它将继续等待(大概永远)。

如果主线程在修改共享数据之前锁定了互斥锁proceed,这种情况本来可以避免。

我认为这就是说“即使共享变量是原子的,也必须在互斥锁下对其进行修改才能正确地将修改发布到等待线程”时的情况。

关于c++ - 如果在互斥锁下没有修改共享原子变量,则无法正确发布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38147825/

相关文章:

c++ - 如何使用gcc在centos 6.4中使用gcc64的旧版本进行编译

c++ - 装饰方法时减少样板

c++ - 获取没有显式特征的整数模板参数的有符号/无符号变体

c++ - vector 的高效移动

C++11 正则表达式子串匹配

C++ 理解类和构造函数

c++ - 为什么需要使用 "WINAPI*"作为语法来为 DLL 中的函数声明函数指针

c++ - 将局部变量绑定(bind)到闭包的最便宜的方法

c++ - 为什么我需要 std::condition_variable?

c++ - 这个可变参数模板是如何工作的?