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

如何在不使用Lambda的情况下调用std::condition_variable::wait(lock, pred)

解决std::condition_variable无Lambda谓词的生产者消费者问题

问题背景

现有一段基于std::condition_variable实现的生产者消费者C++代码,逻辑可正常运行,但编码规范禁止使用Lambda表达式。原代码中std::condition_variable::wait方法使用Lambda作为谓词,尝试直接传入bool变量(如wait(g_ready))无法正常工作,需修改为符合规范的实现方式。

原代码

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

std::mutex g_mutex;
std::condition_variable g_cv;

bool g_ready = false;
int g_data = 0;

int produceData() {
  int randomNumber = rand() % 1000;
  std::cout << "produce data: " << randomNumber << "\n";
  return randomNumber;
}

void consumeData(int data) { std::cout << "receive data: " << data << "\n"; }

void consumer() {
  int data = 0;
  while (true) {
    std::unique_lock<std::mutex> ul(g_mutex);
    g_cv.wait(ul, []() { return g_ready; });
    consumeData(g_data);
    g_ready = false;
    ul.unlock();
    g_cv.notify_one();
  }
}

void producer() {
  while (true) {
    std::unique_lock<std::mutex> ul(g_mutex);
    g_data = produceData();
    g_ready = true;
    ul.unlock();
    g_cv.notify_one();
    ul.lock();
    g_cv.wait(ul, []() { return g_ready == false; });
  }
}

void consumerThread(int n) { consumer(); }

void producerThread(int n) { producer(); }

int main() {
  int times = 100;
  std::thread t1(consumerThread, times);
  std::thread t2(producerThread, times);
  t1.join();
  t2.join();
  return 0;
}

错误尝试

直接传入bool变量:

g_cv.wait(ul, g_ready);

此方式无法正常工作,因为wait的谓词参数需要是可调用对象(能通过()触发调用),而bool是值类型,不满足可调用要求,同时无法处理线程的虚假唤醒问题。


解决方案

可以通过仿函数(函数对象)或全局普通函数替代Lambda作为谓词,两种方式均符合编码规范且能正确处理虚假唤醒。

方案1:使用仿函数(推荐,封装性更好)

定义两个结构体作为谓词,重载operator()实现检查逻辑:

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

std::mutex g_mutex;
std::condition_variable g_cv;

bool g_ready = false;
int g_data = 0;

// 检查g_ready是否为true的谓词
struct IsReady {
    bool operator()() const {
        return g_ready;
    }
};

// 检查g_ready是否为false的谓词
struct IsNotReady {
    bool operator()() const {
        return !g_ready;
    }
};

int produceData() {
  int randomNumber = rand() % 1000;
  std::cout << "produce data: " << randomNumber << "\n";
  return randomNumber;
}

void consumeData(int data) { std::cout << "receive data: " << data << "\n"; }

void consumer() {
  int data = 0;
  while (true) {
    std::unique_lock<std::mutex> ul(g_mutex);
    // 使用IsReady仿函数替代Lambda
    g_cv.wait(ul, IsReady());
    consumeData(g_data);
    g_ready = false;
    ul.unlock();
    g_cv.notify_one();
  }
}

void producer() {
  while (true) {
    std::unique_lock<std::mutex> ul(g_mutex);
    g_data = produceData();
    g_ready = true;
    ul.unlock();
    g_cv.notify_one();
    ul.lock();
    // 使用IsNotReady仿函数替代Lambda
    g_cv.wait(ul, IsNotReady());
  }
}

void consumerThread(int n) { consumer(); }

void producerThread(int n) { producer(); }

int main() {
  int times = 100;
  std::thread t1(consumerThread, times);
  std::thread t2(producerThread, times);
  t1.join();
  t2.join();
  return 0;
}

方案2:使用全局普通函数

定义全局函数实现检查逻辑,直接传入函数指针作为谓词:

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

std::mutex g_mutex;
std::condition_variable g_cv;

bool g_ready = false;
int g_data = 0;

// 检查g_ready是否为true
bool isReady() {
    return g_ready;
}

// 检查g_ready是否为false
bool isNotReady() {
    return !g_ready;
}

int produceData() {
  int randomNumber = rand() % 1000;
  std::cout << "produce data: " << randomNumber << "\n";
  return randomNumber;
}

void consumeData(int data) { std::cout << "receive data: " << data << "\n"; }

void consumer() {
  int data = 0;
  while (true) {
    std::unique_lock<std::mutex> ul(g_mutex);
    // 传入函数指针
    g_cv.wait(ul, isReady);
    consumeData(g_data);
    g_ready = false;
    ul.unlock();
    g_cv.notify_one();
  }
}

void producer() {
  while (true) {
    std::unique_lock<std::mutex> ul(g_mutex);
    g_data = produceData();
    g_ready = true;
    ul.unlock();
    g_cv.notify_one();
    ul.lock();
    // 传入函数指针
    g_cv.wait(ul, isNotReady);
  }
}

void consumerThread(int n) { consumer(); }

void producerThread(int n) { producer(); }

int main() {
  int times = 100;
  std::thread t1(consumerThread, times);
  std::thread t2(producerThread, times);
  t1.join();
  t2.join();
  return 0;
}

关键说明

  • std::condition_variable::wait的谓词必须是可调用对象,返回bool值:wait会在被唤醒后调用该对象,若返回true则继续执行,否则重新进入等待状态,以此处理虚假唤醒问题。
  • 直接传入bool变量既不满足可调用要求,也无法处理虚假唤醒,会导致线程逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:02:13