【问题标题】:What could happen if two threads access the same bool variable at the same time?如果两个线程同时访问同一个 bool 变量会发生什么?
【发布时间】:2011-12-07 00:57:21
【问题描述】:

我有一个跨平台的 c++ 程序,我在其中使用 boost 库来创建一个异步计时器。
我有一个全局变量:

bool receivedInput = false;

一个线程等待并处理输入

string argStr;
while (1) 
{
     getline(cin, argStr);
     processArguments(argStr);
     receivedInput = true;
}

另一个线程运行一个计时器,其中每 10 秒调用一次回调。在那个回调中,我检查我是否收到了一条消息

if (receivedInput)
{
    //set up timer to fire again in 10 seconds
    receivedInput = false;
}
else
    exit(1);

那么这样安全吗?对于线程 2 中的读取,我认为这无关紧要,因为条件将评估为真或假。但我不确定如果两个线程同时尝试设置 receivedInput 会发生什么。我还让我的计时器比我期望接收输入的时间长 3 倍,所以我不担心比赛条件。

编辑: 为了解决这个问题,我在设置接收输入时使用了 boost::unique_lock,在读取接收输入时使用了 boost::shared_lock。我使用了来自here的示例

【问题讨论】:

  • ¤ 如果您想知道它是否安全,那么它不是。无论某些东西在技术上是否安全,线程的情况是这样的,如果你不理解它,那么即使它一开始就完美,它也会在短时间内产生错误。碰巧的是,代码在技术上是不安全的,但实际上是安全的。例如,从技术上讲,“检查”线程可能在if 处暂停,而“输入”线程处理了七行。但实际上这不会发生,但使用像 Bad Things™ 这样的代码发生。 :-) 干杯&hth。

标签: c++ multithreading timer boost-asio


【解决方案1】:

这从根本上来说是不安全的。在线程 1 将 true 写入 receivedInput 后,不能保证线程 2 会看到新值。例如,编译器可能会优化您的代码,在将 receivedInput 用作 if 条件或将其缓存在寄存器中时对它的值做出某些假设,因此您不能保证在评估 if 条件的时间。此外,编译器和 CPU 都可能会更改读写顺序以进行优化,例如true 可能会在getLine()processArguments() 之前写入receivedInput

此外,依靠时间进行同步是一个非常糟糕的主意,因为您通常无法保证每个线程将在给定时间间隔内获得的 CPU 时间量,或者它是否会在给定时间间隔内被调度.

一个常见的错误是认为制作receivedInput volatile 可能会有所帮助。事实上,volatile 保证值实际上是读/写到主内存(而不是例如缓存在寄存器中),并且变量的读取和写入是相对于彼此排序的。但是,它不保证volatile 变量的读取和写入相对于其他指令是有序的。

您需要内存屏障或适当的同步机制才能按预期工作。

【讨论】:

    【解决方案2】:

    您必须检查您的线程标准。假设我们谈论的是 POSIX 线程,这是明确未定义的行为——一个对象可能不会被一个线程访问,而另一个线程正在或可能正在修改它。 任何事情都可能发生。

    【讨论】:

    • 截至 2011 年 9 月,您的线程标准可能是 C++ 标准!
    • @SteveJessop 我一直忘记这件事!
    【解决方案3】:

    如果你的线程使用 receivedInput 的值来控制独立的代码块,而不是相互同步,有一个简单的解决方案:

    在receivedInput前添加“volatile”,这样编译器就不会进行优化,防止线程共享receivedInput的值。

    【讨论】:

    • 我不想-1你,因为你是新人,我不想让你离开,但我不希望volatile对多线程传播有用的误解.没用,volatile 与线程无关,也不是同步方法。
    • 感谢您的评论。是的,我在这里犯了一个错误,两个线程将新值分配给同一个变量。这里需要同步。但是volatile肯定和多线程有关。 “一般来说, volatile 关键字旨在防止编译器对假定变量值不能“自行更改”的代码应用任何优化。(我从维基百科重新检查):)
    • 请注意,多线程不仅仅需要禁用对变量的优化。
    猜你喜欢
    • 2020-11-15
    • 2019-11-03
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    相关资源
    最近更新 更多