读写操作C ++的线程安全性

时间:2013-12-23 21:43:13

标签: c++ thread-safety pthreads

阅读有关取消和pthreads的信息,在我看来,无限循环的线程的最佳实践不是取消线程,而是创建一个将由线程检查的标志。

这种情况意味着在某些时候,某个线程可能会在有人写入该标志时尝试读取该标志。这个线程安全吗?我如何安全地同时使用get_flag()和set_flag()?

5 个答案:

答案 0 :(得分:6)

鉴于有多人评论说“在实践中”可以阅读标志而没有任何事情真的发生,我想首先指出一篇关于benign data races的好文章。仔细阅读本文应该澄清,如果没有同步原语,即使共享bool,您也可以获得有趣的行为。

一种显而易见的方法是使用std::atomic<bool>安全地从不同的线程读取和写入bool。如果您无法使用std::atomic<T>,则需要找到合适的替代品,可能是互斥或特定于平台的原语。

答案 1 :(得分:3)

与所有线程间共享状态一样,要么使用线程安全的类/库作为标志,要么在由互斥锁,锁或其他适当的同步原语保护的关键部分中自己保护它。

答案 2 :(得分:2)

虽然从技术上讲,在一个线程中设置变量并在没有保护的情况下在另一个线程中读取变量可能是未定义的行为,但这是一个案例(极少数),在大多数现代的情况下无关紧要平台。

如果子线程在检查变量的过程中被抢占,它可能会在当前迭代中错过(或不),但会在下一次捕获它。如果在设置变量时主线程被抢占,则子线程可能会错过它(或者,再次,不是),并在下一次迭代中检测它。简而言之,通常无需担心。

答案 3 :(得分:1)

pthreads标准在一个线程中修改一个值,而在另一个线程未定义的行为中修改它。实际上,如果您使用volatile bool,它将适用于您可能遇到的每个平台。如果您想要严格正确,可以使用互斥锁来保护标志,使用原子操作或使用内存屏障。

答案 4 :(得分:1)

如果标志只有两个状态(二进制),则解决方案非常简单 - 使用bool或int的volatile变量。

设置int变量应该是flag = 1flag = 0而不是++flagflag++

该标志必须是易失性的,因此它在使用(读/写)后不会驻留在寄存器中。

语法是:

volatile int flag;volatile bool flag;