可以在同一条件变量上等待多个线程
Can multiple threads wait on the same condition variable?
我正在尝试了解如何更好地使用条件变量,并且我有以下代码。
行为。
代码的预期行为是:
- 每个线程打印"线程">
- 程序等待直到用户按Enter
- 当用户按ENTER时,每个线程都会调用notify_one一次
- 所有线程打印"线程">
代码的观察到的行为是:
- 每个线程打印"线程" n 等待(预期(
- 程序等待,直到用户按Enter (预期(
- 当用户按ENTER时,每个线程(预期( notify_one被调用一次
- 线程之一打印"线程" n ready&quot&quot&quot&quot&quot of thuts ofers。(???(
问题。
为什么代码悬挂?以及如何在相同条件变量上等待多个线程?
代码
#include <condition_variable>
#include <iostream>
#include <string>
#include <vector>
#include <thread>
int main() {
using namespace std::literals::string_literals;
auto m = std::mutex();
auto lock = std::unique_lock(m);
auto cv = std::condition_variable();
auto wait_then_print =[&](int id) {
return [&, id]() {
auto id_str = std::to_string(id);
std::cout << ("thread " + id_str + " waiting.n");
cv.wait(lock);
// If I add this line in, the code gives me a system error:
// lock.unlock();
std::cout << ("thread " + id_str + " ready.n");
};
};
auto threads = std::vector<std::thread>(16);
int counter = 0;
for(auto& t : threads)
t = std::thread(wait_then_print(counter++));
std::cout << "Press enter to continue.n";
std::getchar();
for(int i = 0; i < counter; i++) {
cv.notify_one();
std::cout << "Notified one.n";
}
for(auto& t : threads)
t.join();
}
输出
thread 1 waiting.
thread 0 waiting.
thread 2 waiting.
thread 3 waiting.
thread 4 waiting.
thread 5 waiting.
thread 6 waiting.
thread 7 waiting.
thread 8 waiting.
thread 9 waiting.
thread 11 waiting.
thread 10 waiting.
thread 12 waiting.
thread 13 waiting.
thread 14 waiting.
thread 15 waiting.
Press enter to continue.
Notified one.
Notified one.
thread 1 ready.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
Notified one.
这是未定义的行为。
为了等待条件变量,条件变量必须通过最初锁定Mutex 的相同的精确线程等待。您不能将MUTEX锁定在一个执行线程中,然后在另一个线程中等待条件变量。
auto lock = std::unique_lock(m);
此锁定在主执行线程中获得。之后,主执行线程创建所有这些多个执行线程。这些执行线程中的每一个执行以下执行:
cv.wait(lock)
在此处调用wait()
的执行线程未获得静音锁,因此这是未定义的行为。
更仔细地看一下您在这里尝试做的事情,这表明您只需移动
即可获得预期的结果auto lock = std::unique_lock(m);
在每个新执行线程执行的lambda内部。
由于各种竞赛条件,您还需要仅使用notify_all()
而不是多次调用notify_one()
。请记住,wait()
会自动解锁MUTEX并在条件变量上等待,并且wait()
仅在线程被条件变量通知后成功地重新锁定MUTEX后才返回。
相关文章:
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 等待线程的最佳方式是什么
- std::thread从函数启动,无需等待线程完成
- 带有共享缓冲区的两个等待线程(生产者/消费者)
- std::condition_variable::notify_one() 不会唤醒等待线程
- 在退出进程时等待线程完成
- 如何正确等待线程中的信号
- 如何等待线程直到它开始运行
- 在纯虚拟类的析构函数中等待线程死亡会导致运行时错误
- 更改可报警/可等待线程的上下文
- C++11 std::线程并等待线程完成
- 我如何在Qt中等待线程完成而不阻塞其执行
- Notify_all不唤醒等待线程
- 如何使用boost条件变量来等待线程完成处理
- 等待线程结束(c++)
- 等待线程超时:冻结
- 等待线程
- 等待线程/s直到另一个线程/s结束
- 有效地等待线程池中的所有任务完成