我有一个跨平台的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
中的一个例子答案 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的值。