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

C++ thread与condition_variable:程序是否可能永久无法终止?

C++条件变量程序终止问题及修改验证

你认为下方的C++源代码可能永久无法终止:假设所有waiter线程均已进入等待状态,此时waker线程调用notify_all(),线程t1被唤醒并执行任务,其他线程虽被唤醒,但因mutex被t1占用而回到等待状态,最终永久休眠,导致程序无法结束。你修改了waiter函数,在执行完任务后解锁并调用notify_all(),想确认修改是否正确。

原代码

#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>

using namespace std;

mutex m;
condition_variable cv;

bool isStop = false;

void waiter()
{
    unique_lock<mutex> ul(m);
    cv.wait(ul, []() { return isStop; });

    // ...do something...
}

void waker()
{
    this_thread::sleep_for(chrono::seconds(1));

    unique_lock<mutex> ul(m);
    isStop = true;
    ul.unlock();

    cv.notify_all();
}

void main()
{
    vector<thread> ts;
    for (int i = 0; i < 100; ++i)
        ts.emplace_back(waiter);

    thread w(waker);

    for (auto& t : ts)
        t.join();
    w.join();
}

修改后的waiter函数

void waiter()
{
    unique_lock<mutex> ul(m);
    cv.wait(ul, []() { return isStop; });

    // ...do something...

    ul.unlock();
    cv.notify_all();
}

解答

首先纠正一个误解:原代码并不会出现你担心的永久休眠问题。

原因在于cv.wait(ul, []() { return isStop; })的工作机制:线程被唤醒后,会先重新获取互斥锁,然后再次检查谓词条件(也就是isStop是否为true)。当waker线程已经把isStop设为true,所有被notify_all()唤醒的waiter线程,哪怕一开始没抢到锁,等锁被释放后,重新获取锁时会发现isStop已经是true,直接退出等待逻辑,不会再回到休眠状态。

再看你的修改:

  • 手动调用ul.unlock()属于冗余操作,unique_lock作为局部变量,函数执行完毕时会自动释放锁。
  • 每个waiter线程都调用cv.notify_all()完全没必要,会产生大量无意义的通知,徒增系统开销。

结论:你的修改是不必要的,原代码本身逻辑正确,不会出现永久无法终止的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:55:17