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

C++中条件变量与互斥锁的工作机制及代码无输出问题排查

条件变量与互斥锁的工作机制及代码问题分析

一、条件变量与互斥锁的基本工作逻辑

  • 互斥锁(mutex):用于保护共享资源,确保同一时间仅一个线程能访问被锁资源,避免数据竞争。
  • 条件变量(condition_variable):实现线程间同步,让线程等待特定条件满足后再执行,避免无意义的轮询等待。
  • 结合使用的核心流程:
    1. 线程先获取互斥锁,锁定共享资源。
    2. 检查目标条件:若不满足,调用wait()方法,此时互斥锁会被自动解锁,线程进入阻塞等待状态。
    3. 当其他线程通过notify_one()或notify_all()唤醒等待线程时,被唤醒的线程会重新自动获取互斥锁,再次检查条件(防止虚假唤醒),条件满足后继续执行后续代码。

二、关于“wait时互斥锁是否解锁”的明确回答

是的。调用condition_variable::wait(unique_lock<mutex>&)时,会自动执行两个操作:

  1. 解锁传入的互斥锁,允许其他线程获取锁访问资源。
  2. 将当前线程挂起,进入等待队列,直到被通知唤醒。
    线程被唤醒后,wait()会重新尝试获取互斥锁,成功获取后才会返回,继续执行后续代码。

三、你的代码无输出的原因分析

先贴出你的代码:

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

condition_variable cv;
mutex mu;

void thread1()
{
    mu.lock();
    unique_lock lck(mu);
    cv.wait(lck);
    cout << 1;
}

void thread2()
{
    this_thread::sleep_for(1s);
    mu.lock();
    cv.notify_all();
    cout << 2;    
}

int main()
{
    thread t1(thread1);
    thread t2(thread2);
    this_thread::sleep_for(2s);
}

问题出在以下几点:

  1. thread1中的锁重复锁定:
    你先手动调用mu.lock()锁住互斥锁,之后又用unique_lock lck(mu)尝试再次获取该锁。unique_lock的默认构造(传入mutex参数)会尝试锁定mutex,此时mutex已被手动锁住,导致unique_lock构造阻塞,永远到不了cv.wait(lck)步骤。
  2. thread2无法获取锁:
    thread1通过mu.lock()占用锁后,thread2执行到mu.lock()时会被阻塞,永远无法执行notify_all()和输出操作。
  3. 主线程提前退出:
    主线程仅sleep2秒,此时t1和t2都处于阻塞状态,主线程退出会直接终止整个进程,导致两个线程的代码都没机会完成输出。

四、修复后的代码示例

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

condition_variable cv;
mutex mu;

void thread1()
{
    unique_lock<mutex> lck(mu); // 用unique_lock自动管理锁,禁止手动lock
    cv.wait(lck);
    cout << 1 << endl;
}

void thread2()
{
    this_thread::sleep_for(1s);
    {
        lock_guard<mutex> lck(mu); // 用lock_guard自动管理锁的生命周期
        cv.notify_all();
        cout << 2 << endl;
    }
}

int main()
{
    thread t1(thread1);
    thread t2(thread2);
    t1.join(); // 等待t1执行完成
    t2.join(); // 等待t2执行完成
}

修复要点:

  • 禁止手动调用mutex::lock()后再用unique_lock或lock_guard管理同一个锁,应让RAII类(unique_lock/lock_guard)自动处理锁的获取与释放,避免死锁或重复锁定问题。
  • 主线程需用join()等待子线程完成,而非单纯sleep,确保子线程有足够时间执行完毕。
  • thread2中用lock_guard临时获取锁,通知完成后自动释放,避免长期占用锁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:53:26