我可以在没有互斥锁的线程中读取bool变量吗? [重复]

问题描述 投票:2回答:3

这个问题在这里已有答案:

如果我不使用互斥锁,以下源代码有什么问题吗?

bool bStop = false;

void thread1_fun()
{
    while (!bStop)
    {
        doSomething();
    }
}

void thread2_fun()
{
    bStop = true;
}
c++ multithreading mutex
3个回答
14
投票

写入一个线程中的对象而另一个线程完全访问该对象是未定义的行为。

除非你特别通知编译器应该有一个围栏,例如使用std::atomicstd::mutex等,所有的赌注都是关闭的。

编译器有权重新编写代码,如下所示:

bool bStop = false;

void thread1_fun()
{
    const bool stopped = bStop;
    // compiler reasons: "because there is no fence, the variable clearly cannot
    // have changed to true, since no-other thread will modify it, since
    // to modify it without a fence would be UB." 
    while (!stopped)  
    {  
        doSomething();
    }
}

void thread2_fun()
{
    // this happens in my thread's view of the world, 
    // but no other thread need see it.
    bStop = true;  
} 

9
投票

如果我不使用互斥锁,以下源代码有什么问题吗?

是的,你有一个竞争条件,导致未定义的行为。

您需要使用std::atomic<bool>或使用同步原语(如bStop)保护对std::mutex的写入/读取。


与(遗憾的)普遍看法相反,将bStop标记为volatile并不能解决任何问题。 volatile限定符与线程安全无关。


1
投票

在一个线程中写入变量并在另一个线程中读取该变量的值是数据竞争。具有数据竞争的程序具有未定义的行为;这意味着C ++标准没有告诉你该程序将做什么。您可以通过使变量原子或使用各种同步来避免数据竞争,最常见的是std::mutexstd::condition_variable

通过分析您正在编译的代码的详细信息,编译器如何从该源代码生成目标代码的详细信息以及硬件如何处理的详细信息,您可以在不同步的情况下可靠地“工作”程序生成的对象代码。然后,如果你改变这三个中的任何一个,你必须重新进行分析,因为这些改变可能不再“起作用”了。当然,如果你这样做,那么你就会被高级语言所拯救的所有细节所困扰。除非在极少数情况下,这根本不值得努力。正确使用该语言。

© www.soinside.com 2019 - 2024. All rights reserved.