boost 库(C++11 标准之前)提供了对线程的支持。作为其支持的一部分,它还提供了“barrier”的实现,这是一个允许同步的简单类。引用boost website :
“屏障是一个简单的概念。也称为集合点,它是多个线程之间的同步点。屏障是为特定数量的线程 (n) 配置的,当线程到达屏障时,它们必须等待,直到所有 n 个线程都已到达。一旦第 n 个线程到达屏障,所有等待线程都可以继续执行,并且屏障将重置。”
从 Boost 1.54 开始,屏障(wait)主要功能的实现如下所示:
bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
可以看出,屏障是可重复使用的:一旦构建完成,第一次使用后不需要销毁。
我现在的问题是:变量 m_ Generation 的作用是什么?我假设 boost 库的作者有理由包含它。每次屏障重置/准备好重用时,它都会递增,但目的是什么?它是私有(private)变量,因此无法从外部读取。同样的问题可以通过 wait() 函数内的简单内部 bool 变量轻松解决,而无需使用私有(private)类变量。
最佳答案
简而言之,需要m_ Generation
来处理spurious wakeups .
生成计数器与条件变量结合使用,向所有在屏障上等待的线程发出信号,表明它们可以自由地继续:
一旦有
m_threshold
线程到达屏障,其生成数就会增加,并且条件变量会发出信号。这会导致等待线程(即那些较早到达屏障的线程)从m_cond.wait(lock)
中唤醒。现在,等待线程可以从
m_cond.wait(lock)
中唤醒 other reasons 。这就是m_ Generation
发挥作用的地方:如果它发生了更改,则屏障已重置并且线程可以继续进行。如果m_ Generation
仍然包含相同的值,则线程需要返回到m_cond.wait(lock)
。
在 wait()
中使用自动变量将无法实现此目的,因为每个线程都有自己的实例。
关于c++ - 为什么 Boost 库在线程屏障的实现中使用 m_ Generation 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26190853/