带任务队列的线程池出现无响应死锁问题求助
线程池永久卡住问题排查
我需要将任务拆分到多个std::thread工作线程中,待所有任务完成后再继续执行。基于Stack Overflow的回答实现了一个线程池类,但基准测试中程序会无报错永久卡住。
最小复现代码
#include <atomic> #include <condition_variable> #include <functional> #include <iostream> #include <mutex> #include <queue> #include <thread> #include <vector> class Pool { public: const int worker_count; bool to_terminate = false; std::atomic<int> unfinished_tasks = 0; std::mutex mutex; std::condition_variable condition; std::vector<std::thread> threads; std::queue<std::function<void()>> jobs; void thread_loop() { while (true) { std::function<void()> job; { std::unique_lock<std::mutex> lock(mutex); condition.wait(lock, [&] { return (!jobs.empty()) || to_terminate; }); if (to_terminate) return; job = jobs.front(); jobs.pop(); } job(); unfinished_tasks -= 1; } } public: Pool(int size) : worker_count(size) { if (size < 0) throw std::invalid_argument("Worker count needs to be a positive integer"); for (int i = 0; i < worker_count; ++i) threads.push_back(std::thread(&Pool::thread_loop, this)); }; ~Pool() { { std::unique_lock lock(mutex); to_terminate = true; } condition.notify_all(); for (auto &thread : threads) thread.join(); threads.clear(); }; void queue_job(const std::function<void()> &job) { { std::unique_lock<std::mutex> lock(mutex); jobs.push(job); unfinished_tasks += 1; // std::cout << unfinished_tasks; } condition.notify_one(); } void wait() { while (unfinished_tasks) { ; // spinlock }; } }; int main() { constexpr int worker_count = 8; constexpr int vector_size = 1 << 10; Pool pool = Pool(worker_count); std::vector<int> test_vector; test_vector.reserve(vector_size); for (int i = 0; i < vector_size; ++i) test_vector.push_back(i); std::vector<int> worker_odd_counts(worker_count, 0); std::function<void(int)> worker_task = [&](int thread_id) { int chunk_size = vector_size / (worker_count) + 1; int my_start = thread_id * chunk_size; int my_end = std::min(my_start + chunk_size, vector_size); int local_odd_count = 0; for (int ii = my_start; ii < my_end; ++ii) if (test_vector[ii] % 2 != 0) ++local_odd_count; worker_odd_counts[thread_id] = local_odd_count; }; for (int iteration = 0;; ++iteration) { std::cout << "Jobs.." << std::flush; for (int i = 0; i < worker_count; ++i) pool.queue_job([&worker_task, i] { worker_task(i); }); std::cout << "..queued. " << std::flush; pool.wait(); int odd_count = 0; for (auto elem : worker_odd_counts) odd_count += elem; std::cout << "Iter:" << iteration << ". Odd:" << odd_count << '\n'; } }
问题排查情况
根据终端输出,问题似乎出现在任务入队阶段。我查阅了视频、文档和博客文章,尝试替换锁类型、使用原子操作,但仍未找到根本原因。
环境差异
- 复现环境:Windows 10 + AMD Ryzen 4750U + GCC 12.2.0 x86_64-w64-mingw32,程序无法突破15000次迭代就会卡住
- 无问题环境:Visual Studio Community 2022,程序运行超过150万次迭代仍未出现问题
内容的提问来源于stack exchange,提问作者Dudly01
相关产品推荐
相关产品推荐

