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

为每个Worker分配独立std::function的线程池触发段错误崩溃

问题描述

我之前基于Stack Overflow的回答实现了一个线程池,它通过单个std::queue将std::function<void()>任务分发给多个std::thread工作线程,有效提升了程序运行效率。

为进一步优化,由于我仅需运行有限数量的函数,计划移除队列,改用变量实现:让第n个工作线程执行std::vector<std::function<void()>>中的第n个任务。但测试程序触发了「Segmentation fault (core dumped)」错误,目前尚未定位问题。

以下是我编写的最小复现代码,功能为统计vector中的奇数元素(思路源自Scott Meyers的《Cpu Caches and Why You Care》):

#include <algorithm>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <mutex>
#include <stdexcept> // std::invalid_argument
#include <thread>
#include <vector>

// Thread pool with a std::function for each worker.
class Pool {
  public:
    enum class Status {
        idle,
        working,
        terminate
    };

    const int worker_count;

    std::vector<Status> statuses;
    std::vector<std::mutex> mutexes;
    std::vector<std::condition_variable> conditions;
    std::vector<std::thread> threads;
    std::vector<std::function<void()>> jobs;

    void thread_loop(int thread_id)
    {
        std::puts("Thread started");
        auto &my_status = statuses[thread_id];
        auto &my_mutex = mutexes[thread_id];
        auto &my_condition = conditions[thread_id];
        auto &my_job = jobs[thread_id];

        while (true) {
            std::unique_lock<std::mutex> lock(my_mutex);
            my_condition.wait(lock, [this, &my_status] { return my_status != Status::idle; });

            if (my_status == Status::terminate)
                return;

            my_job();
            my_status = Status::idle;
            lock.unlock();
            my_condition.notify_one(); // Tell the main thread we are done
        }
    }

  public:
    Pool(int size) : worker_count(size), statuses(size, Status::idle), mutexes(size), conditions(size), threads(), jobs(size)
    {
        if (size < 0)
            throw std::invalid_argument("Worker count needs to be a positive integer");
    };
    ~Pool()
    {
        for (int i = 0; i < worker_count; ++i) {
            std::unique_lock lock(mutexes[i]);
            statuses[i] = Status::terminate;
            lock.unlock(); // Unlock before notifying
            conditions[i].notify_one();
        }

        for (auto &thread : threads)
            thread.join();
        threads.clear();
    };

    void start_threads()
    {
        threads.resize(worker_count);
        jobs.resize(worker_count);

        for (int i = 0; i < worker_count; ++i) {
            statuses[i] = Status::idle;
            jobs[i] = []() { std::puts("I am running"); };
            threads[i] = std::thread(&Pool::thread_loop, this, i);
        }
    }

    void set_and_start_job(const std::function<void(int)> &job)
    {
        for (int i = 0; i < worker_count; ++i) {
            std::unique_lock lock(mutexes[i]);
            jobs[i] = [&job, i]() { job(i); };
            statuses[i] = Status::working;
            lock.unlock();
            conditions[i].notify_one();
        }
    }

    void wait()
    {
        for (int i = 0; i < worker_count; ++i) {
            auto &my_status = statuses[i];
            std::unique_lock lock(mutexes[i]);
            conditions[i].wait(lock, [this, &my_status] { return my_status != Status::working; });
        }
    }
};

int main()
{
    constexpr int worker_count = 1;
    constexpr int vector_size = 1 << 10;

    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);

    const auto 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;
    };

    Pool pool = Pool(worker_count);
    pool.start_threads();
    pool.set_and_start_job(worker_task);
    pool.wait();

    int odd_count = 0;
    for (auto elem : worker_odd_counts)
        odd_count += elem;
    std::cout << odd_count << '\n';
}

内容的提问来源于stack exchange,提问作者Dudly01

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:42:16