c++ - 为什么 Boost 库在线程屏障的实现中使用 m_ Generation 变量?

标签 c++ multithreading boost boost-thread barrier

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/

相关文章:

c++ - 指针算法 C++ 的段错误

C++ const 数组追加

regression - C\C++ 中的 LIBLINEAR

c++ - SIGINT 正常关闭

c++ - boost::fibonacci_heap 复制构造函数损坏源堆

c++ - 行号 0 超出范围 0..-1 LIBPQ

c# - 我需要将线程访问同步到 int 吗?

wpf - 调用线程无法访问该对象,因为其他线程拥有它

java - 具有多个实例的单例?

c++ - dynamic_bitset,让我的程序崩溃