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

如何用C++11线程等待多线程完成?多线程阻塞问题求助

问题分析与解决方案

首先,你的代码里存在几个关键问题导致多线程测试时程序无法正常结束,我来逐一拆解:

核心问题点

  • 条件变量与互斥锁不配对:在wait()方法中,你使用了m_waitForRunFinishMutex来配合m_cond.wait(),但在run()方法里,却是用m_mutex来调用m_cond.wait()。条件变量的设计要求必须和同一个互斥锁绑定使用,否则会触发未定义行为,这是导致producer2无法被正确唤醒的主要原因之一。
  • 虚假唤醒的处理逻辑错误:原wait()里用if (m_running)后递归调用wait(),这种方式不仅会导致锁的管理混乱,还无法可靠处理条件变量的虚假唤醒。正确的做法是用while循环持续检查条件,直到满足退出条件。
  • wait()方法的递归调用风险:递归调用wait()会导致多次加锁(虽然你手动解锁了,但逻辑上依然混乱),很容易引发死锁或者唤醒失效的问题。

修正后的代码实现

针对这些问题,我们主要修正wait()方法,同时确保条件变量和互斥锁的配对使用:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
using namespace std;

class Producer {
public:
    Producer(int a_id): m_id(a_id), m_running(false), m_ready(false), m_terminate(false) {
        m_thread = thread(&Producer::run, this);
        while (!m_ready) {}
    }
    ~Producer() {
        terminate();
        m_thread.join();
    }
    void wait() {
        unique_lock<mutex> lock(m_mutex); // 和run()里用同一个锁
        // 用while循环处理虚假唤醒,直到m_running变为false
        while (m_running) {
            m_cond.wait(lock);
        }
        cout << "wait exit " << m_id << endl;
    }
    void start() {
        unique_lock<mutex> lock(m_mutex);
        m_running = true;
        m_cond.notify_all();
    }
    void terminate() {
        unique_lock<mutex> lock(m_mutex);
        m_terminate = true;
        m_running = true; // 确保线程能从wait中唤醒
        m_cond.notify_all();
    }
    void run() {
        m_ready = true;
        do {
            unique_lock<mutex> lock(m_mutex);
            while (!m_running) {
                m_cond.wait(lock);
            }
            if (!m_terminate) {
                cout << "running thread: " << m_id << endl;
            }
            m_running = false;
            m_cond.notify_all();
        } while (!m_terminate);
    }
private:
    int m_id;
    bool m_running;
    bool m_ready;
    bool m_terminate;
    thread m_thread;
    mutex m_mutex; // 只保留一个锁,和条件变量配对
    condition_variable m_cond;
};

// 测试代码
int main() {
    Producer producer1(1);
    Producer producer2(2);
    producer1.start();
    producer2.start();
    producer1.wait();
    producer2.wait();
    return 0;
}

修正说明

  1. 移除了多余的m_waitForRunFinishMutex,统一使用m_mutex和m_cond配对,确保条件变量的操作都是基于同一个锁。
  2. 重构wait()方法,使用while循环检查m_running状态,正确处理虚假唤醒,同时避免递归调用。
  3. 在start()和terminate()方法中也添加了锁保护,确保对共享变量m_running和m_terminate的修改是线程安全的。

运行修正后的代码,你会得到预期的输出:

running thread: 1
running thread: 2
wait exit 1
wait exit 2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:55:47