我通过通常受相应互斥锁保护的公共可访问成员变量来命令我的线程。
我的问题是:如果单个变量在写访问期间受到互斥锁的保护,它是否应该在读访问期间也受到保护,还是我可以简单地读取它?
示例:
一个线程检查是否应该做一些特殊的事情
(doSpecial写在另一个线程中)
// some code
if (doSpecial) {
// code
}
// some code
这种读访问是否应该受到互斥锁的保护?
是的,如果变量在一个线程上修改并在其他线程上访问,那么所有访问都必须受到互斥锁的保护。没有它,或者其他一些同步方法,就不能保证修改是原子的(因此其他线程可能会读取损坏的值),也不能保证其他线程会看到修改后的值(它可能保留在一个处理器的缓存中并且永远不会传播给他人)。
在 C++11 中,对于简单类型,您可能会考虑std::atomic
而不是受互斥锁保护的非原子变量。
我不确定,但是写一个整数或单个布尔值不是原子的会很奇怪。我相信写一个双精度(64位)也可能是原子的。
如果 doSpecial 是两个线程直接访问的布尔变量,则需要用“volatile”来限定它。这将阻止编译器为其使用缓存。
如果您不这样做,则执行测试的函数(if (doSpecial))可能会将变量映射到处理器内部缓存中,并且if -test 可能永远不会看到值更改。
使用互斥锁不会阻止编译器对变量进行这种优化。
最好的方法是通过函数访问值:
if ( isSpecial() ) ...
setSpecial( bool ){ ... }
如果它们在多个布尔值上工作,它允许您在这两个函数中添加互斥锁管理