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
相关产品推荐
相关产品推荐

