在这里删除c volatile是否安全?

从m_flag的定义中删除volatile是否安全?
如果m_flag不是volatile,那么什么会阻止编译器优化掉这个循环的条件:while(!m_flag)m_cv.wait(lock); ?
标准(后C 11)是否明确规定在这种情况下禁止这种优化?
#include <mutex>
#include <condition_variable>
#include <future>
#include <iostream>
using namespace std;

class foofoo
{
    volatile bool m_flag;
    mutex m_mutex;
    condition_variable m_cv;

public:
    void DoWork()
    {
        m_flag = false;
        unique_lock<mutex> lock(m_mutex);
        auto junk = async(std::launch::async,[this]()
        {
            {
                unique_lock<mutex> lock(m_mutex);
                m_flag = true;
            }
            m_cv.notify_one();
        });
        while (!m_flag) m_cv.wait(lock);
        cout << "ququ" << endl;
    }
};

int main()
{
    foofoo f;
    f.DoWork();
}

解决方法

通常,volatile和多线程在C 11中是正交的.使用volatile既不会添加也不会删除数据争用.

在这种情况下,m_flag = true;在async([intro.execution] / p14)启动的线程中释放互斥锁之前,它被排序,后者又与m_cv.wait(lock)中的互斥锁的后续获取同步([thread.mutex.requirements. mutex] / p11,25),然后在随后读取m_flag之前对其进行排序. m_flag = true;因此,线程发生在之后的读取之前,因此发生在后续读取之前. ([intro.multithread] / p13-14)

由于m_flag没有其他副作用,m_flag = true;是读取的可见副作用([intro.multithread] / p15),因此读取必须读取可见副作用所存储的内容,即为真.

无论是否使用volatile,“优化”该条件的编译器都是不符合的.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...