【发布时间】:2013-01-22 19:48:41
【问题描述】:
假设我们有一个简单的类:
class example
{
bool m_isCanceled;
example() : m_isCanceled(false) {}
public:
void cancel() { m_isCanceled = true; }
void doWork()
{
for (int i = 0; i < MAX_RETRIES; ++i)
{
// Slow
doStuff();
if (m_isCanceled)
{
return;
}
}
}
}
如果我们在一个线程上调用example::doWork(),然后在一段时间后我们在另一个线程上调用example::cancel(),那么在第一个线程看到m_isCanceled 现在为真之前是否存在限制?
在类似的情况下,我建议我们使用互斥锁保护 m_isCanceled,但我的同事说第一个线程最多会在额外的迭代后看到更新。是这样吗?
【问题讨论】:
-
不,他不对——没有内存栅栏,第一个线程可能永远看到更新。
-
如果您使用的是 C++11,您应该将
m_isCanceled声明为atomic<bool>,如果您不是,则将其访问与互斥锁同步。 -
@Andy :幸运的是,对于那些使用旧工具集的人来说,Boost 1.53 将包含新的 Boost.Atomic 库。 :-]
-
@ildjarn:很高兴听到,感谢您分享信息 :)
-
您的
m_isCanceled上至少需要volatile- 这应该会阻止它被缓存在循环中的寄存器中。然而,在某些架构上,这还不够,因为缓存不会在另一个内核写入变量时更新——在这种情况下,您必须使用原子类型操作。
标签: c++ multithreading mutex