多线程ConcurrentQueue调用wait_and_pop时崩溃问题求助
ConcurrentQueue 偶发崩溃问题排查
我在项目中实现了一个ConcurrentQueue,但它偶尔会导致程序崩溃,崩溃点在poped_value = this->the_queue.front();语句处。我猜测崩溃原因是队列为空,但按逻辑此时队列不该为空——调用front()前已经通过while (the_queue.empty())循环确保队列非空,且当前线程持有锁,其他线程无法操作队列弹出元素。
以下是我最初的实现代码:
#include <pthread.h> #include <queue> template <typename Data> class ConcurrentQueue { private: std::queue<Data> the_queue; pthread_mutex_t mutex; pthread_cond_t condition; public: ConcurrentQueue() { this->mutext = PTHREAD_MUTEX_INITIALIZER; this->condition = PTHREAD_COND_INITIALIZER; } ~ConcurrentQueue() {} void Push(Data &data) { pthread_mutext_lock(&this->mutext); this->the_queue.push(data); pthread_mutex_unlock(&this->mutext); pthead_cond_signal(&this->condition); } void wait_and_pop(Data& poped_value) { pthead_mutex_lock(&this->mutext); while (this->the_queue.empty()){ pthead_cond_wait(&this->condition,&this->mutext); } poped_value = this->the_queue.front(); this->the_queue.pop(); pthead_mutex_unlock(&this->mutext); } };
问题根源分析
你的代码里存在多个致命错误,直接导致锁机制完全失效,引发竞态条件:
- 大量拼写错误:
- 成员变量名为
mutex,但构造函数、Push、wait_and_pop中全写成了mutext,导致实际的mutex根本没被初始化,锁操作都是在操作一个不存在的变量。 pthread相关API拼写错误:pthead_cond_signal、pthead_mutex_lock、pthead_cond_wait里的pthead应该是pthread,这些错误会导致调用未定义的函数,或者完全跳过正确的锁操作,让多个线程同时访问队列。
- 成员变量名为
- 锁和条件变量初始化错误:
PTHREAD_MUTEX_INITIALIZER和PTHREAD_COND_INITIALIZER是用于静态初始化的,不能在构造函数里通过赋值的方式初始化。这种错误初始化会导致锁无法正常工作,多个线程可以同时操作队列,破坏了队列的线程安全性。 - 析构函数未清理资源:
没有调用pthread_mutex_destroy和pthread_cond_destroy销毁锁和条件变量,可能导致资源泄漏。
正是因为锁机制失效,多个线程可以同时进入wait_and_pop,当一个线程弹出队列最后一个元素后,另一个线程已经通过了empty()检查,此时队列已经为空,调用front()就会触发崩溃。
修正后的代码
#include <pthread.h> #include <queue> #include <utility> // 用于std::move template <typename Data> class ConcurrentQueue { private: std::queue<Data> the_queue; // 静态初始化锁和条件变量,确保正确初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t condition = PTHREAD_COND_INITIALIZER; public: ConcurrentQueue() = default; ~ConcurrentQueue() { // 销毁锁和条件变量,清理资源 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&condition); } // 禁止拷贝和移动,避免多线程环境下的非法操作 ConcurrentQueue(const ConcurrentQueue&) = delete; ConcurrentQueue& operator=(const ConcurrentQueue&) = delete; ConcurrentQueue(ConcurrentQueue&&) = delete; ConcurrentQueue& operator=(ConcurrentQueue&&) = delete; // 支持const引用的Push void Push(const Data &data) { pthread_mutex_lock(&mutex); the_queue.push(data); pthread_mutex_unlock(&mutex); pthread_cond_signal(&condition); } // 支持移动语义的Push,提升性能 void Push(Data &&data) { pthread_mutex_lock(&mutex); the_queue.push(std::move(data)); pthread_mutex_unlock(&mutex); pthread_cond_signal(&condition); } void wait_and_pop(Data& poped_value) { pthread_mutex_lock(&mutex); // 循环检查队列状态,避免虚假唤醒 while (the_queue.empty()) { pthread_cond_wait(&condition, &mutex); } poped_value = the_queue.front(); the_queue.pop(); pthread_mutex_unlock(&mutex); } };
关键修正点说明
- 修正所有拼写错误:确保
mutex变量名和pthread系列API调用完全正确,锁机制可以正常工作。 - 正确初始化锁和条件变量:通过静态初始化的方式在成员变量声明时直接赋值,避免构造函数里的错误赋值操作。
- 添加资源清理逻辑:析构函数中销毁锁和条件变量,避免资源泄漏。
- 禁止拷贝移动:多线程环境下拷贝队列会导致严重的线程安全问题,因此禁用拷贝构造和移动构造。
- 增强Push灵活性:增加移动语义的Push重载,支持右值推送,提升性能。
内容的提问来源于stack exchange,提问作者user24542906
相关产品推荐
相关产品推荐

