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

pthread_cond_broadcast无法唤醒处于pthread_cond_wait等待状态的线程的Linux平台问题求助

pthread_cond_broadcast无法唤醒处于pthread_cond_wait等待状态的线程的Linux平台问题求助

我现在遇到了一个线程相关的棘手问题,想请教各位大佬。我正在开发一个需要执行异步任务的程序,采用线程池的方式实现。为了避免线程在无任务时空跑消耗资源,我用pthread_cond_wait让它们进入阻塞状态,当有新任务到来时再用pthread_cond_signal唤醒其中一个线程。

这里需要说明的是,我必须使用C++98标准,所以没法用std::thread库,只能依赖C的pthread系列函数来实现。

目前在MacOS平台上一切运行正常,暂时没发现任何问题。

下面是我的ThreadPool类定义:

#include <queue>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>

class ThreadPool {
public:
    ThreadPool(size_t numThreads);
    ~ThreadPool();

    void    enqueueTask(void (*function)(int, int), int client_fd, int backend_fd);

    void    kill();

private:
    std::vector<pthread_t> workers;
    std::queue<void (*)(int, int)> tasks;
    std::queue<std::pair<int, int> > taskArgs;

    pthread_mutex_t queueMutex;
    pthread_cond_t condition;
    bool stop;

    static void* workerThread(void* arg);
    void run();
};

对应的实现代码如下:

ThreadPool::ThreadPool(size_t numThreads): stop(false)
{
    pthread_mutex_init(&queueMutex, NULL);
    pthread_cond_init(&condition, NULL);

    for (size_t i = 0; i < numThreads; ++i) {
        pthread_t worker;
        pthread_create(&worker, NULL, workerThread, this);
        workers.push_back(worker);
    }
}

ThreadPool::~ThreadPool()
{
    if (!stop) {
        this->kill();
    }   
}

void    ThreadPool::kill()
{
    pthread_mutex_lock(&queueMutex);
    stop = true;
    pthread_cond_broadcast(&condition);
    pthread_mutex_unlock(&queueMutex);

    for (size_t i = 0; i < workers.size(); ++i) {
        pthread_cancel(workers[i]);
    }

    for (size_t i = 0; i < workers.size(); ++i) {
        pthread_join(workers[i], NULL);
    }

    pthread_mutex_destroy(&queueMutex);
    pthread_cond_destroy(&condition);
}

void    ThreadPool::enqueueTask(void (*function)(int, int), int client_fd, int backend_fd)
{
    pthread_mutex_lock(&queueMutex);
    tasks.push(function);
    taskArgs.push(std::make_pair(client_fd, backend_fd));
    pthread_cond_signal(&condition);
    pthread_mutex_unlock(&queueMutex);
}

void    *ThreadPool::workerThread(void* arg)
{
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

    ThreadPool* pool = (ThreadPool*)arg;
    pool->run();
    return NULL;
}

void    ThreadPool::run()
{
    while (true) {
        pthread_mutex_lock(&queueMutex);

        while (!stop && tasks.empty()) {
            pthread_cond_wait(&condition, &queueMutex);
        }

        if (stop) {
            pthread_mutex_unlock(&queueMutex);
            return;
        }

        void (*task)(int, int) = tasks.front();
        std::pair<int, int> args = taskArgs.front();
        tasks.pop();
        taskArgs.pop();

        pthread_mutex_unlock(&queueMutex);
        
        pthread_testcancel();

        task(args.first, args.second);

        pthread_testcancel();
    }
}

我的问题出在Linux平台(至少Ubuntu是这样):当我调用ThreadPool::kill()函数尝试停止所有线程时,pthread_cond_broadcast似乎无法唤醒那些阻塞在pthread_cond_wait的线程,导致主线程在调用pthread_join时一直阻塞,整个程序彻底卡死,只能通过发送SIGKILL信号才能终止进程。

举个实际运行的例子:

bool running = true;

static void interruptHandler(int sig_int) {
    (void)sig_int;
    running = false;
}

void task(int a, int b)
{
    size_t i = a + b;
    size_t r = 0;

    for (; i < 1000000; i++)
        r = a + i;
    sleep(1);
    std::cout << "task done: " << r << std::endl;
}

int main(void)
{
    ThreadPool *pool = new ThreadPool(4);

    signal(SIGINT, interruptHandler);

    while (running)
    {
        sleep(1);
        pool->enqueueTask(task, 0, 0);
    }

    pool->kill();
}

当我按下CTRL+C触发中断后,进程直接卡死,只能靠SIGKILL才能终止...

补充说明一下,我设置PTHREAD_CANCEL_DEFERRED是因为希望线程能完成当前任务后再被取消,但问题似乎并不是任务阻塞导致的——哪怕我把main函数改成下面这样,问题依然存在:

int main(void)
{
    ThreadPool *pool = new ThreadPool(4);

    signal(SIGINT, interruptHandler);

    while (running)
        ;

    pool->kill();
} 

我完全搞不懂为什么Linux会有这种奇怪的行为,也不知道该如何解决这个阻塞问题。恳请大家帮忙分析一下,谢谢了!

备注:内容来源于stack exchange,提问作者Maxence Gama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:58:05