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

Condition Variable Wait阻塞Thread Join,线程安全队列挂起问题

问题分析与解决

核心问题

  1. 队列无数据导致阻塞:你的ThreadSafeQueue自始至终没有被推入任何数据,wait_and_pop的逻辑就是阻塞等待队列非空——它会释放锁并挂起线程,直到队列有数据且条件谓词!data_.empty()为真才会继续执行。这直接导致第一个线程卡在条件变量的等待步骤,join会一直等待线程完成,程序因此挂起。
  2. 对条件变量wait方法的误解:cv.wait()是阻塞式调用,并非非阻塞。它的作用是让线程进入等待状态,直到被其他线程的notify_one()/notify_all()唤醒,且唤醒后会重新检查条件谓词,只有满足条件才会继续执行。
  3. 未定义行为:你的main函数中直接使用&ts_que,但根本没有声明ThreadSafeQueue<int> ts_que实例,这属于未定义行为,实际运行中可能引发崩溃或异常。
  4. 线程串行执行:循环中创建线程后立刻调用join,会导致线程逐个串行执行,完全失去了多线程并发的意义。

修正后的代码示例

#include <mutex>
#include <queue>
#include <thread>
#include <vector>
#include <iostream>

template <typename T>
class ThreadSafeQueue {
 private:
  std::queue<T> data_;
  mutable std::mutex mut_;
  std::condition_variable cv_;

 public:
  ThreadSafeQueue() {}
  ThreadSafeQueue(const ThreadSafeQueue& other) {
    std::lock_guard<std::mutex> lk(other.mut_);
    data_ = other.data_;
  }

  void push(T item) {
    std::lock_guard<std::mutex> lk(mut_);
    data_.push(std::move(item));
    cv_.notify_one();
  }

  void wait_and_pop(T& item) {
    std::unique_lock<std::mutex> ulk(mut_);
    cv_.wait(ulk, [this] { return !data_.empty(); });
    item = std::move(data_.front());
    data_.pop();
  }

  bool try_pop(T& item) {
    std::lock_guard<std::mutex> lk(mut_);
    if (data_.empty()) return false;
    item = data_.front();
    data_.pop();
    return true;
  }

  bool empty() const {
    std::lock_guard<std::mutex> lk(mut_);
    return data_.empty();
  }
};

int main() {
    ThreadSafeQueue<int> ts_que; // 初始化队列实例

    // 推入数据,让消费线程有数据可处理
    ts_que.push(1);
    ts_que.push(2);
    ts_que.push(3);

    std::vector<int> output(3);
    std::vector<std::thread> threads;

    // 先创建所有消费线程
    for (int i = 0; i < 3; i++) {
        threads.push_back(std::thread(&ThreadSafeQueue<int>::wait_and_pop,
                                      &ts_que, std::ref(output[i])));
    }

    // 统一等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    // 验证结果
    for (int num : output) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}

关键修正点

  • 新增ThreadSafeQueue<int> ts_que实例,修复未定义行为。
  • 在启动消费线程前推入数据,确保wait_and_pop的条件能被满足,线程不会一直阻塞。
  • 将join移到循环外,让所有线程先启动再统一等待,实现真正的并发执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:40:34