Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.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++_Multithreading_C++11_Thread Safety - Fatal编程技术网

C++ 互斥和变量更新

C++ 互斥和变量更新,c++,multithreading,c++11,thread-safety,C++,Multithreading,C++11,Thread Safety,需要验证一个思维过程,假设我设置了一个线程,如下所示 bool threadRun=true; std::mutex threadMutex; std::condition_variable event; std::thread processThread(process); void process() { while(threadRun) { if(noWork()) { std::unique_lock<std

需要验证一个思维过程,假设我设置了一个线程,如下所示

bool threadRun=true;
std::mutex threadMutex;
std::condition_variable event;
std::thread processThread(process);

void process()
{
    while(threadRun)
    {
        if(noWork())
        {
            std::unique_lock<std::mutex> lock(threadMutex);

            if(threadRun)
            {
                if(!getWork()) //try to get work, return false if no work
                    event.wait(lock);
            }

            continue;
        }

        doWork();
    }
}

void stopThread()
{
    {
        std::unique_lock<std::mutex> lock(threadMutex);
        threadRun=false;
    }
    event.notify_all();
    processThread.join();
}
bool threadRun=true;
std::互斥线程互斥;
std::条件变量事件;
std::线程进程线程(进程);
无效过程()
{
while(threadRun)
{
if(noWork())
{
std::唯一锁(threadMutex);
如果(线程运行)
{
如果(!getWork())//尝试获取工作,如果没有工作,则返回false
事件。等待(锁定);
}
继续;
}
销钉();
}
}
void stopThread()
{
{
std::唯一锁(threadMutex);
threadRun=false;
}
事件。通知所有人();
processThread.join();
}

由于threadRun不在线程中的互斥锁下,因此不能保证调用stopThread会实际停止线程,因为当有工作要做时,不需要缓存刷新。但是,当没有工作且锁定被执行时,这将导致缓存刷新,threadRun保证会被更新,正确?

< P> C++中的数据竞争是未定义的行为。< /P> 现在,你可能认为这意味着“好吧,我同意他们错过了一个阅读,他们最终会得到它”。但是UB是编译器可以自由假设不会发生的事情

事实上,在没有锁或其他同步的情况下读取
threadRun
,这意味着编译器可以、可能并且应该假设任何其他线程中没有人会修改
threadRun

因此,代码可以优化为:

if(threadRun)
  while(true)
也就是说,编译器可以读取
threadRun
一次,如果它可以证明没有人能够以定义的方式更改它的值,那么就不用麻烦再次读取它

现在,如果编译器不能证明这一点,它必须读取
threadRun
。所以你的UB更像是“应该”工作。在某些平台上,硬件本身已将
threadRun
缓存在每处理器(或线程)缓存中,而另一个线程向其写入的事实在未知时间段(可能永远)内不会反映在工作线程中

更进一步说,智能编译器可能会注意到您正在读取
threadRun
,而没有同步。然后它可以用它来证明,无论是否同步,没有人可以在另一个线程中写入
threadRun

一旦证明了这一点,它还可以在互斥对象中取消对
threadRun
的检查

不要执行未定义的行为,除非您希望验证程序从现在开始直到每次编译结束时生成的程序集,即使它“工作”,或者收益巨大且值得冒险


threadRun
替换为
std::atomic\u bool
。在最坏的情况下,您将损失一点点性能并获得正确性。

数据竞争就是数据竞争,您认为缓存刷新与此有什么关系?
threadRun
将在不进行任何同步的情况下读取。这是一个必须解决的问题。不需要引入缓存刷新之类的系统详细信息。如果您遵守语言规则,抽象机器将确保一切正常。如果您正在寻找快速解决方案,您可以使
threadRun
a。谢谢,只需要用UB蝙蝠向上敲打头部作为提醒。