6

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

这听起来是个好主意,并且示例使它看起来对程序员非常友好。不幸的是,我认为示例代码调用了未定义的行为。该提案说latch::~latch()

破坏闩锁。如果闩锁在其他线程中wait()或正在调用时被销毁count_down(),则行为未定义。

请注意,作为用途的描述,它说的是“in wait()”而不是“blocked 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();
}

wait()唤醒和返回的线程与离开范围时锁存器的破坏之间是否存在竞争条件?除此之外,所有的thread对象都被泄露了。count_down如果调度程序在返回之前没有运行所有工作线程并且start_latch对象离开范围,那么我认为会导致未定义的行为。大概解决方法是在返回之后但在返回之前迭代向量join()delete所有工作线程。count_down

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

注意:一个或多个工作线程似乎还没有开始等待,因此将调用wait()一个被破坏的锁存器。


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

4

1 回答 1

4

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

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

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

阿拉斯代尔

于 2013-05-15T19:45:51.950 回答