Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 卸下c+是否安全+;在这里?_C++_C++11_Volatile - Fatal编程技术网

C++ 卸下c+是否安全+;在这里?

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

m_flag
的定义中删除
volatile
是否安全? 如果
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();
}
#包括
#包括
#包括
#包括
使用名称空间std;
福福班
{
易变布尔穆旗;
互斥体mu互斥体;
条件变量m_cv;
公众:
无效销钉()
{
m_标志=假;
唯一的_锁(m_互斥锁);
自动垃圾=async(std::launch::async,[this]()
{
{
唯一的_锁(m_互斥锁);
m_标志=真;
}
m_cv.通知_one();
});
而(!m_flag)m_cv.wait(lock);

cout一般来说,
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.multi-thread]/p13-14)

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


“优化”的编译器除去该条件,不管是否使用了volatile,都是不符合要求的。

在循环中调用了
wait
,因此编译器无法消除它。除了
wait
对编译器来说可能或多或少是不透明的之外,它在循环中包含互斥锁/解锁有效地防止了编译器的任何消除。因此,
volatile
在那里是完全无用的。

谢谢!因此,换句话说,如果循环体不改变循环条件,但包含一个同步“点”,为了优化它,编译器必须分析循环条件是否会受到另一个线程可以与同一个“点”同步的“可见副作用”?在实践中,编译器可能会放弃,永远不会尝试优化这些循环。我的意思是“优化循环的条件”。我刚刚意识到我说的是“循环”“在任何地方,虽然循环显然会保留,但会变成一个无限循环…@MaxGalkin只要你不写数据竞争,编译器必须确保先前释放互斥的线程所做的更改对随后获取相同互斥的线程可见。我不确定我是否会说“永远不要尝试”,但只要代码没有数据竞争,一致性编译器就不会有任何意外。我认为,如果在该方法中使用局部布尔变量而不是m_标志,编译器将可以自由地优化循环的条件,因为局部变量对其他线程不可见……关于“等待”在循环体内部…如果使用local,那么可能会-我不是编译器专家。编译器消除任何东西的唯一方法(据我所知)是为了证明变量不能在任何其他地方更改。对不透明函数的任何调用都可能极大地阻碍此功能,编译器将放弃尝试。但是,如果使用局部变量,如果您没有将其地址传递到任何地方,则肯定不会在任何其他地方设置它。然后,此语句您的回答不正确:“您在循环中调用了
wait
,因此编译器无法消除它。”.仅仅调用
wait
不足以阻止消除…@Max Galkin,我的评论是关于循环消除的-它不能在OP中消除。但是如果你有
bool flag=false;
这是在
while(flag)上使用的
那么,在我看来,编译器可能会认为这是一条死胡同,永远不会执行它,因为条件总是假的。但这肯定与您的问题不同。您的问题中没有局部变量。