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

多线程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);
    }
};

关键修正点说明

  1. 修正所有拼写错误:确保mutex变量名和pthread系列API调用完全正确,锁机制可以正常工作。
  2. 正确初始化锁和条件变量:通过静态初始化的方式在成员变量声明时直接赋值,避免构造函数里的错误赋值操作。
  3. 添加资源清理逻辑:析构函数中销毁锁和条件变量,避免资源泄漏。
  4. 禁止拷贝移动:多线程环境下拷贝队列会导致严重的线程安全问题,因此禁用拷贝构造和移动构造。
  5. 增强Push灵活性:增加移动语义的Push重载,支持右值推送,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:18:11