条件变量(Condition Variable)
条件变量(Condition Variable)是C++多线程中用于线程间等待与通知的同步机制,常与互斥量(mutex) 一起使用。
👉 条件变量 = 线程“等一个条件成立再继续”的工具
不满足就睡眠,满足了被别人叫醒。
为什么需要条件变量?
如果只用 mutex,线程可能要不停轮询(忙等):
while (!ready) { } // 浪费 CPU
条件变量可以:
-
线程阻塞等待(不占 CPU)
-
条件满足后被通知唤醒
基本使用流程(核心 4 步)
等待线程
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, 条件);
通知线程
cv.notify_one(); // 唤醒一个
cv.notify_all(); // 唤醒全部
完整示例:生产者 – 消费者(Condition Variable)
功能说明
-
生产者线程:不断往队列里放数据
-
消费者线程:队列为空就等待,有数据就取
-
使用 条件变量避免忙等
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <chrono>
std::queue<int> dataQueue; // 共享队列
std::mutex mtx; // 互斥量
std::condition_variable cv; // 条件变量
bool finished = false; // 生产是否结束
// 生产者
void producer() {
for (int i = 1; i <= 5; ++i) {
{
std::lock_guard<std::mutex> lock(mtx);
dataQueue.push(i);
std::cout << "Producer produced: " << i << std::endl;
}
cv.notify_one(); // 通知消费者
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
// 生产结束
{
std::lock_guard<std::mutex> lock(mtx);
finished = true;
}
cv.notify_all(); // 唤醒所有等待的消费者
}
// 消费者
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
// 等待:队列非空 或 生产结束
cv.wait(lock, [] {
return !dataQueue.empty() || finished;
});
// 队列有数据 → 消费
while (!dataQueue.empty()) {
int value = dataQueue.front();
dataQueue.pop();
std::cout << "Consumer consumed: " << value << std::endl;
}
// 生产结束且队列为空 → 退出
if (finished) {
break;
}
}
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
std::cout << "All done." << std::endl;
return 0;
}
Producer produced: 1
Consumer consumed: 1
Producer produced: 2
Consumer consumed: 2
...
All done.
一、程序启动(main)
int main() {
std::thread t1(producer);
std::thread t2(consumer);t1.join();
t2.join();
}
-
主线程创建 生产者线程 t1
-
主线程创建 消费者线程 t2
-
主线程阻塞在
join(),等它们结束
二、消费者先跑(常见情况)
① consumer 线程进入 while(true)
std::unique_lock<std::mutex> lock(mtx);
-
consumer 拿到互斥锁
-
此时队列:
空 -
finished = false
② consumer 调用 wait
cv.wait(lock, [] { return !dataQueue.empty() || finished; });
wait 内部发生的事(非常关键):
-
判断条件:
!dataQueue.empty() || finished // false
-
条件不成立 →
-
自动释放 mutex
-
consumer 线程 进入休眠(阻塞)
👉 此时:
-
consumer ❌ 不占 CPU
-
mutex 现在是 空闲的
三、生产者开始工作
③ producer 线程第一次循环
std::lock_guard<std::mutex> lock(mtx); dataQueue.push(1);
-
producer 拿到 mutex
-
往队列放入
1 -
作用域结束 → mutex 自动释放
④ producer 通知
cv.notify_one();
-
操作系统 唤醒一个正在 wait 的线程
-
此时 consumer 被标记为“可运行”
⚠️ 但:consumer 还没真正跑
四、消费者被唤醒
⑤ consumer 被唤醒后
wait 做的事:
cv.wait(...) // 内部继续
重新尝试加锁 mutex(必须成功)
再次检查条件:
!dataQueue.empty() || finished // true
条件成立 → wait 返回
⑥ consumer 消费数据
while (!dataQueue.empty()) { int value = dataQueue.front(); dataQueue.pop(); }
-
消费
1 -
队列再次为空
五、重复这个过程
⑦ producer 继续生产
push(2) → notify push(3) → notify ...
⑧ consumer 重复
wait → 醒 → 加锁 → 消费 → 再 wait
六、生产结束
⑨ producer 设置结束标志
{ std::lock_guard<std::mutex> lock(mtx); finished = true; } cv.notify_all();
关键点:
-
修改
finished在锁内(线程安全) -
notify_all()防止 consumer 永久睡眠
七、消费者安全退出
⑩ consumer 再次醒来
cv.wait(lock, [] { return !dataQueue.empty() || finished; });
-
此时:
finished == true -
即使队列空,条件也成立
-
wait返回
⑪ consumer 判断退出条件
if (finished) { break; }
-
跳出
while(true) -
consumer 线程结束
八、程序结束
-
producer 线程结束
-
consumer 线程结束
-
join()返回 -
main 结束
更多推荐

所有评论(0)