You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++线程池线程数超核心数时退出码139的问题及修改方案

线程池崩溃问题的修复方案

核心错误分析

  1. Vector越界访问:init()中调用threads.reserve(threads_num)仅预留内存空间,vector的实际元素数量仍为0,直接通过threads[i]赋值会触发越界访问,属于未定义行为。线程数超过2时更易崩溃,是因为内存越界的影响具有随机性,低线程数时可能恰好未触发非法内存访问。

  2. 条件变量的错误使用:run()中用if(tasks.empty())判断是否等待,而非while循环。当shutdown()调用notify_all()唤醒所有线程时,部分线程唤醒后tasks队列可能为空,此时执行tasks.front()和tasks.pop()会直接访问空队列,导致崩溃。

  3. 未等待线程结束:shutdown()仅设置停止标记并唤醒线程,但未调用join()等待所有线程执行完毕,程序退出时线程可能仍在运行,引发资源泄漏或崩溃。

  4. 析构函数未清理线程:默认析构函数不会处理未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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:00:34