C++20 std::latch调试求助:调用taskDone.wait()时程序阻塞
调试C++20 std::latch阻塞问题
你的代码出现阻塞的核心原因是std::jthread的自动join行为导致线程串行执行,形成死锁。
问题分析
在main函数的for循环中,每次创建std::jthread ac{worker_f, i};后,循环迭代结束时ac会被销毁,而std::jthread的析构函数会自动等待线程执行完毕(调用join())。这意味着线程是逐个串行启动并执行完毕的:
- 前3个worker线程依次执行,每次将
latch计数减1,最终latch变为0。 - 当创建第4个worker线程(i=3)时,
latch.try_wait()返回true,线程进入分支等待taskDone的信号。但此时main函数被卡在等待这个worker线程完成,而worker线程又在等待main执行taskDone.count_down(),形成死锁,程序彻底阻塞,后续的第5个线程根本没机会启动。
修复方案
将std::jthread存储到容器中,让所有线程可以并发启动,避免main提前等待单个线程结束。修改后的代码如下:
#include <chrono> #include <iostream> #include <thread> #include <latch> #include <vector> // 新增头文件 using namespace std::chrono_literals; std::latch latch{ 3 }; std::latch taskDone{ 1 }; void worker_f(int this_id) { if (latch.try_wait()) { std::printf("worker %d comes late, full slot ... waiting for the task done\n", this_id); taskDone.wait(); std::printf("task done, worker %d exit\n", this_id); } else { std::printf("worker %d comes on time, there is a task for him\n", this_id); latch.count_down(); } std::this_thread::sleep_for(100ms); } int main() { std::vector<std::jthread> workers; // 用容器存储线程 workers.reserve(5); // 预分配空间 for (int i = 0; i < 5; ++i) { workers.emplace_back(worker_f, i); // 线程存入容器,不会立即析构join } std::cout << "hello" << std::endl; std::printf("waiting for worker\n"); latch.wait(); std::printf("full slot, doing task\n"); taskDone.count_down(); std::printf("task done\n"); std::this_thread::sleep_for(1000ms); }
修复后执行流程
- 所有5个worker线程同时启动,前3个线程会抢占
latch的计数并减到0。 - 后2个线程发现
latch已计数为0,进入等待taskDone的分支。 - main函数在启动所有线程后,等待
latch计数归0,随后执行taskDone.count_down()释放等待的线程。 - 所有线程最终都能完成执行,输出完整的日志。
内容的提问来源于stack exchange,提问作者felix
相关产品推荐
相关产品推荐

