如果两个线程同时访问同一个bool变量会发生什么?

时间:2011-12-07 00:57:21

标签: c++ multithreading timer boost-asio

我有一个跨平台的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中的读取,我认为无关紧要,因为条件将评估为true或false。但我不确定如果两个线程同时尝试设置receivedInput会发生什么。我也把我的计时器比我期望接收输入的时间长3倍,所以我不担心比赛情况。

编辑: 为了解决这个问题,我在读取receiveInput时设置了receiveInput和boost :: shared_lock时使用了boost :: unique_lock。我使用了here

中的一个例子

3 个答案:

答案 0 :(得分:5)

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

此外,依赖于同步的时间是一个非常糟糕的主意,因为通常你不能保证每个线程在给定的时间间隔内将获得的CPU时间量,或者它是否将在给定的时间间隔内进行调度

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

如果您的线程使用receivedInput的值来控制独立的代码块,但不能彼此同步,那么有一个简单的解决方案:

在receiveInput之前添加“volatile”,因此编译器不会进行优化,防止线程共享receiveInput的值。