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

Max*_*kin 6 c++ volatile c++11

volatilem_flag这里的定义中删除是否安全?如果m_flag不挥发,什么会阻止优化掉这个循环的条件编译: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();
}
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 10

通常,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),因此该读必须读什么存储在由可见的副作用,即,true.

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

  • @MaxGalkin只要您不编写数据争用,编译器必须确保先前释放互斥锁的线程所做的更改对随后获取相同互斥锁的线程可见.我不确定我是否会说"永不尝试",但只要代码没有数据竞争,就不应该对符合标准的编译器产生任何意外. (2认同)