C++ N3600中的“闩锁”示例中是否存在竞争条件?
建议在C++14(又名C++1y)中包含一些新的线程同步原语:锁存器和屏障。建议是C++ N3600中的“闩锁”示例中是否存在竞争条件?,c++,race-condition,language-lawyer,c++14,C++,Race Condition,Language Lawyer,C++14,建议在C++14(又名C++1y)中包含一些新的线程同步原语:锁存器和屏障。建议是 这听起来是个好主意,而且这些示例使它看起来对程序员非常友好。不幸的是,我认为示例代码调用了未定义的行为。提案中提到的latch::~latch(): 破坏门闩。如果在其他线程处于wait()或调用count\u down()时闩锁被破坏,则行为未定义 请注意,它表示“在wait()”而不是“在wait()中被阻止”,正如count\u down()的描述所使用的那样 然后提供以下示例: 第二个用例的示例如
latch::~latch()
:
破坏门闩。如果在其他线程处于wait()
或调用count\u down()
时闩锁被破坏,则行为未定义
请注意,它表示“在wait()
”而不是“在wait()
中被阻止”,正如count\u 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();
}
void DoWork()
{
锁存器启动锁存器(1);
媒介工作者;
对于(int i=0;i
从wait()
唤醒和返回的线程与闩锁离开作用域时的销毁之间是否存在争用条件?除此之外,所有线程
对象都会泄漏。如果调度程序在倒计时
返回之前没有运行所有工作线程,并且开始锁定
对象离开作用域,那么我认为将导致未定义的行为。大概修复方法是在倒计时
之后返回之前,迭代向量并join()
和删除所有工作线程
示例代码有问题吗
您是否同意提案应该显示一个完整正确的示例,即使任务非常简单,以便审阅者了解使用体验是什么样的
注意:可能有一个或多个工作线程尚未开始等待,因此将在损坏的闩锁上调用wait()
更新:现在有一个新版本的提案,但代表性的例子没有改变。感谢您指出这一点。是的,我认为示例代码(在其辩护中,其意图是简洁的)被破坏了。它可能应该等待线程完成
任何允许线程在wait()中被阻塞的实现几乎肯定会涉及某种条件变量,并且在线程尚未退出wait()时销毁闩锁可能是未定义的
我不知道是否有时间更新这篇论文,但我可以确保下一个版本是固定的
阿拉斯代尔@stefan:我不认为“释放被阻止的线程”包括“等待这些线程至少运行到从wait()
返回为止”。此外,有一个线程可能还没有达到start\u latch.wait()
调用。我同意你的看法。这个例子似乎已经失败了……欢迎来到StackOverflow,感谢您的公开回应。如果你能在下一个版本发布后提供一个链接,那就太好了。7月份在圣克拉拉还有一个SG1会议——我已经在SG1维基上发布了一篇更新的文章,我希望它能在芝加哥之前的邮件中发布(以及圣克拉拉的任何其他变化)。