如果没有在互斥对象下修改共享原子变量,则不能正确发布

Shared atomic variable is not properly published if it is not modified under mutex

本文关键字:变量 不能 对象 共享 修改 如果没有      更新时间:2023-10-16

我正在阅读http://en.cppreference.com/w/cpp/thread/condition_variable上的std::condition_variable,我不明白这个:

即使共享变量是原子的,也必须在互斥,以便正确地将修改发布到等待中线程。

为什么一个共享原子变量在互斥下没有被修改就不能正确发布?如何理解这句话呢?

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

如果一个线程写一个原子对象,而另一个线程读从它,行为是定义良好的(参见内存模型的详细信息数据竞争)

考虑这个例子:

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之前锁定了互斥锁,这种情况就可以避免了。

我认为这就是"即使共享变量是原子的,也必须在互斥锁下修改它,以便正确地将修改发布到等待线程"时的情况。