gpt4 book ai didi

c++ - 破坏条件变量随机丢失通知

转载 作者:IT老高 更新时间:2023-10-28 22:29:34 29 4
gpt4 key购买 nike

给定一个条件变量作为类的成员,我的理解是:

  1. The condition variable is destroyed after the class destructor completes.
  2. Destruction of a condition variable does not need to wait for notifications to have been received.

鉴于这些期望,我的问题是:为什么下面的示例代码随机无法通知等待线程?

#include <mutex>
#include <condition_variable>
#define NOTIFY_IN_DESTRUCTOR

struct notify_on_delete {
std::condition_variable cv;

~notify_on_delete() {
#ifdef NOTIFY_IN_DESTRUCTOR
cv.notify_all();
#endif
}
};

int main () {
for (int trial = 0; trial < 10000; ++trial) {
notify_on_delete* nod = new notify_on_delete();
std::mutex flag;
bool kill = false;

std::thread run([nod, &flag, &kill] () {
std::unique_lock<std::mutex> lock(flag);
kill = true;
nod->cv.wait(lock);
});

while(true) {
std::unique_lock<std::mutex> lock(flag);
if (!kill) continue;
#ifdef NOTIFY_IN_DESTRUCTOR
delete nod;
#else
nod->cv.notify_all();
#endif
break;
}
run.join();
#ifndef NOTIFY_IN_DESTRUCTOR
delete nod;
#endif
}
return 0;
}

在上面的代码中,如果 NOTIFY_IN_DESTRUCTOR 没有定义,那么测试将可靠地运行到完成。但是,当 NOTIFY_IN_DESTRUCTOR 被定义时,测试将随机挂起(通常在几千次试验之后)。

我正在使用 Apple Clang 进行编译:Apple LLVM 版本 9.0.0 (clang-900.0.39.2)目标:x86_64-apple-darwin17.3.0线程模型:posix指定 C++14,编译时设置了 DEBUG 标志。

编辑:

澄清一下:这个问题是关于条件变量实例的指定行为的语义。上面的第二点似乎在以下 quote 中得到了加强。 :

Blockquote Requires: There shall be no thread blocked on *this. [ Note: That is, all threads shall have been notified; they may subsequently block on the lock specified in the wait. This relaxes the usual rules, which would have required all wait calls to happen before destruction. Only the notification to unblock the wait needs to happen before destruction. The user should take care to ensure that no threads wait on *this once the destructor has been started, especially when the waiting threads are calling the wait functions in a loop or using the overloads of wait, wait_­for, or wait_­until that take a predicate. — end note ]

核心语义问题似乎是“阻塞”是什么意思。我目前对上面引用的解释是在该行之后

cv.notify_all(); // defined NOTIFY_IN_DESTRUCTOR

在 ~notify_on_delete() 中,线程测试 not “被阻止”点头 - 也就是说,我目前了解到,在此调用之后,“解除阻止等待的通知” 发生了,所以根据报价,已经满足了继续销毁 condition_variable 实例的要求。

有人能解释一下“被阻止”或“通知解除阻止”,大意是在上面的代码中,对 notify_all() 的调用不满足 ~condition_variable() 的要求吗?

最佳答案

当 NOTIFY_IN_DESTRUCTOR 被定义时:
调用 notify_one()/notify_all() 并不意味着正在等待的线程立即被唤醒,当前线程将等待另一个线程。这只是意味着如果等待线程在当前线程调用通知后的某个时刻唤醒,它应该继续。因此,本质上,您可能会在等待线程唤醒之前删除条件变量(取决于线程的调度方式)。

即使条件变量在另一个线程正在等待它时被删除,它为什么挂起的解释也在于等待/通知操作是使用与条件变量关联的队列来实现的。这些队列持有等待条件变量的线程。释放条件变量意味着摆脱这些线程队列。

关于c++ - 破坏条件变量随机丢失通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48093715/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com