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

C++条件变量满足条件却无限等待的问题排查与修复

条件变量等待线程无限阻塞的修复

原代码

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>

using namespace std;

std::mutex  mtx;
std::condition_variable cv;

int main() {
  int balance = 0;
  std::thread withdraw([&](int amt){
      std::unique_lock<std::mutex> ul(mtx);
      cv.wait(ul, [balance, amt]{ return balance >= amt; });
      balance  -= amt;
      std::cout << "Amount deducted: " << amt << ", current balance: " << balance << endl;
  }, 500);

  std::thread deposit([&](int amt){
      std::lock_guard<mutex> lg(mtx);
      balance += amt;
      std::cout << "Amount added: " << amt << ", current balance: " << balance << endl;
      cv.notify_one();
  }, 1000);

  withdraw.join();
  deposit.join();
  return 0;
}

问题现象

运行时仅输出存款信息,取款线程无限阻塞:

➜  synchronization git:(master) ✗ ./a.out
Amount added: 1000, current balance: 1000

问题根源

你在cv.wait的判断Lambda中用值捕获了balance,这意味着Lambda内部保存的是balance的初始值(0)。即使deposit线程修改了主函数中的balance,Lambda里的balance始终是最初的0,导致balance >= amt的条件永远不成立,取款线程无法被唤醒继续执行。

修复方案

将balance改为引用捕获,让Lambda能访问到balance的最新值,有两种写法:

写法1:显式引用捕获balance

修改等待条件的Lambda:

cv.wait(ul, [&balance, amt]{ return balance >= amt; });

写法2:捕获外部作用域的所有引用

因为外层的withdraw线程Lambda已经用[&]捕获了所有外部变量的引用,内部Lambda可以直接继承这个捕获规则:

cv.wait(ul, [&]{ return balance >= amt; });

修复后的完整代码

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>

using namespace std;

std::mutex  mtx;
std::condition_variable cv;

int main() {
  int balance = 0;
  std::thread withdraw([&](int amt){
      std::unique_lock<std::mutex> ul(mtx);
      cv.wait(ul, [&balance, amt]{ return balance >= amt; }); // 修改捕获方式
      balance  -= amt;
      std::cout << "Amount deducted: " << amt << ", current balance: " << balance << endl;
  }, 500);

  std::thread deposit([&](int amt){
      std::lock_guard<mutex> lg(mtx);
      balance += amt;
      std::cout << "Amount added: " << amt << ", current balance: " << balance << endl;
      cv.notify_one();
  }, 1000);

  withdraw.join();
  deposit.join();
  return 0;
}

预期运行结果

Amount added: 1000, current balance: 1000
Amount deducted: 500, current balance: 500

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:32:02