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绑定的.通过并行运行这些,可以提高吞吐量.
Run Code Online (Sandbox Code Playgroud)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.
注意:似乎有一个或多个工作线程尚未开始等待,因此将调用wait()已销毁的锁存器.
更新:现在有一个新版本的提案,但代表性的例子没有变化.
感谢您指出了这一点。是的,我认为示例代码(在其辩护中,其目的是简洁)已损坏。它可能应该等待线程完成。
任何允许线程在 wait() 中被阻塞的实现几乎肯定会涉及某种条件变量,并且在线程尚未退出 wait() 时销毁锁存器可能是未定义的。
我不知道是否有时间更新论文,但我可以确保下一个版本已修复。
阿拉斯代尔