N3600中的`latch`样本中是否存在竞争条件?

Ben*_*igt 6 c++ race-condition language-lawyer c++14

建议包含在C++ 14(又名C++ 1y)中的是一些新的线程同步原语:锁存器和屏障.提案是

这听起来是个好主意,样本使它看起来非常适合程序员.不幸的是,我认为示例代码调用了未定义的行为.提案说latch::~latch():

摧毁闩锁.如果在其他线程处于wait()或正在调用时销毁锁存器count_down(),则行为未定义.

请注意,它表示"in wait()"而不是"block in wait()",作为使用说明count_down().

然后提供以下示例:

第二用例的示例如下所示.我们需要加载数据然后使用许多线程处理它.加载数据是I/O绑定的,而启动线程和创建数据结构是CPU绑定的.通过并行运行这些,可以提高吞吐量.

void DoWork()
{
    latch start_latch(1);
    vector<thread*> workers;
    for (int i = 0; i < NTHREADS; ++i) {
      workers.push_back(new thread([&] {
        // Initialize data structures. This is CPU bound.
        ...
        start_latch.wait();
        // perform work
        ...
      }));
    }
    // Load input data. This is I/O bound.
    ...
    // Threads can now start processing
    start_latch.count_down();
}
Run Code Online (Sandbox Code Playgroud)

线程唤醒和返回之间是否存在竞争条件wait(),并且当闩锁离开范围时是否会破坏闩锁?除此之外,所有thread对象都泄露了.如果调度程序在count_down返回之前没有运行所有工作线程并且start_latch对象离开作用域,那么我认为将导致未定义的行为.据推测,修复是在返回之后但在返回之前迭代向量join()和delete所有工作线程count_down.

  1. 示例代码有问题吗?
  2. 您是否同意提案应该显示一个完整正确的示例,即使任务非常简单,以便审阅者了解使用体验会是什么样的?

注意:似乎有一个或多个工作线程尚未开始等待,因此将调用wait()已销毁的锁存器.


更新:现在有一个新版本的提案,但代表性的例子没有变化.

Ala*_*osh 4

感谢您指出了这一点。是的,我认为示例代码(在其辩护中,其目的是简洁)已损坏。它可能应该等待线程完成。

任何允许线程在 wait() 中被阻塞的实现几乎肯定会涉及某种条件变量,并且在线程尚未退出 wait() 时销毁锁存器可能是未定义的。

我不知道是否有时间更新论文,但我可以确保下一个版本已修复。

阿拉斯代尔