C++线程池线程数超核心数时退出码139的问题及修改方案
线程池崩溃问题的修复方案
核心错误分析
Vector越界访问:
init()中调用threads.reserve(threads_num)仅预留内存空间,vector的实际元素数量仍为0,直接通过threads[i]赋值会触发越界访问,属于未定义行为。线程数超过2时更易崩溃,是因为内存越界的影响具有随机性,低线程数时可能恰好未触发非法内存访问。条件变量的错误使用:
run()中用if(tasks.empty())判断是否等待,而非while循环。当shutdown()调用notify_all()唤醒所有线程时,部分线程唤醒后tasks队列可能为空,此时执行tasks.front()和tasks.pop()会直接访问空队列,导致崩溃。未等待线程结束:
shutdown()仅设置停止标记并唤醒线程,但未调用join()等待所有线程执行完毕,程序退出时线程可能仍在运行,引发资源泄漏或崩溃。析构函数未清理线程:默认析构函数不会处理未join的线程,程序退出时可能触发异常。
修正后的代码
线程池头文件
#ifndef THREADPOOL__THREADPOOL_V1_H_ #define THREADPOOL__THREADPOOL_V1_H_ #include <mutex> #include <vector> #include <queue> #include <condition_variable> #include <thread> #include <functional> #include <utility> class threadPool_v1 { public: threadPool_v1(int threads_num) : stop(false), threads_num(threads_num) {} ~threadPool_v1() { shutdown(); } threadPool_v1(const threadPool_v1&) = delete; threadPool_v1(threadPool_v1&&) = delete; threadPool_v1& operator=(const threadPool_v1&) = delete; threadPool_v1& operator=(threadPool_v1&&) = delete; void init() { // 改用emplace_back添加线程,避免越界访问 for(int i = 0; i < threads_num; i++) { threads.emplace_back(std::bind(&threadPool_v1::run, this)); } } void shutdown() { std::unique_lock<std::mutex> lock(mtx); if (stop) return; // 避免重复调用shutdown stop = true; lock.unlock(); cond.notify_all(); // 等待所有线程执行完毕 for(auto& t : threads) { if(t.joinable()) { t.join(); } } } bool addTask(std::function<void()> fun) { std::unique_lock<std::mutex> lock(mtx); if(stop) { return false; } tasks.push(std::move(fun)); cond.notify_one(); return true; } void run() { while(!stop) { std::unique_lock<std::mutex> lock(mtx); // 用while循环处理虚假唤醒,确保队列非空或已停止才退出等待 while(tasks.empty() && !stop) { cond.wait(lock); } if(stop) break; // 已停止则直接退出循环 auto task = std::move(tasks.front()); tasks.pop(); lock.unlock(); if(task) { task(); } } } private: std::mutex mtx; std::condition_variable cond; bool stop; int threads_num; std::queue<std::function<void()>> tasks; std::vector<std::thread> threads; }; #endif//THREADPOOL__THREADPOOL_V1_H_
测试代码
#include <iostream> #include <cstdlib> #include "threadPool_v1.h" void printNum() { int num = random(); std::cout << num << std::endl; } int main() { threadPool_v1 pool(4); pool.init(); pool.addTask(printNum); pool.addTask(printNum); pool.addTask(printNum); getchar(); return 0; }
内容的提问来源于stack exchange,提问作者zheng ruan
相关产品推荐
相关产品推荐

