条件变量需与互斥锁配合使用,通过wait()、notify_one()、notify_all()实现线程同步,在生产者-消费者模型中确保数据安全访问与线程协调。

在C++多线程编程中,条件变量(std::condition_variable)是实现线程间同步的重要工具。它通常与互斥锁(std::mutex)配合使用,允许一个或多个线程等待某个条件成立,而另一个线程在条件满足时通知等待中的线程继续执行。
条件变量的基本组件
使用 std::condition_variable 需要包含头文件:
主要涉及以下三个部分:
- std::condition_variable:用于阻塞线程或唤醒其他线程。
- std::mutex:保护共享数据,防止竞争。
- wait()、notify_one()、notify_all():核心操作函数。
基本用法:生产者-消费者模型示例
下面是一个典型的生产者-消费者示例,展示如何使用条件变量协调两个线程:
立即学习“C++免费学习笔记(深入)”;
#include iostream>#include
#include
#include
#include
std::queue
std::mutex mtx;
std::condition_variable cv;
bool finished = false;
void producer() {
for (int i = 0; i std::lock_guard<:mutex> lock(mtx);
data_queue.push(i);
std::cout cv.notify_one(); // 唤醒一个消费者
}
{
std::lock_guard<:mutex> lock(mtx);
finished = true;
cv.notify_all(); // 通知所有等待线程结束
}
}
void consumer() {
while (true) {
std::unique_lock<:mutex> lock(mtx);
// 等待队列非空或任务结束
cv.wait(lock, [] { return !data_queue.empty() || finished; });
if (finished && data_queue.empty()) {
break;
}
int value = data_queue.front();
data_queue.pop();
lock.unlock();
std::cout }
}
int main() {
std::thread p(producer);
std::thread c(consumer);
p.join();
c.join();
return 0;
}
关键点说明
1. wait() 的正确使用方式
cv.wait(lock, predicate) 是推荐写法。它会自动释放锁并阻塞线程,直到被唤醒且谓词为真。这避免了虚假唤醒带来的问题。
2. 使用 std::unique_lock 而不是 lock_guard
因为 wait() 需要能够临时释放和重新获取锁,std::unique_lock 支持这种操作,而 std::lock_guard 不支持。
3. notify_one() vs notify_all()
- notify_one():唤醒一个等待的线程,适用于只有一个消费者的情况。
- notify_all():唤醒所有等待线程,适合广播场景,比如终止信号。
4. 共享状态需用互斥量保护
任何被多个线程访问的变量(如 data_queue 和 finished)都必须在互斥锁保护下访问。
常见错误与注意事项
避免忘记通知
如果生产者没有调用 notify_one() 或 notify_all(),消费者将永远阻塞。
避免在持有锁时做耗时操作
长时间持有锁会影响其他线程效率。例如,把打印操作放在解锁后更安全。
处理虚假唤醒
即使没有被显式通知,wait() 也可能返回。因此必须配合循环或带谓词的 wait() 来确保条件真正满足。
基本上就这些。合理使用条件变量可以让多线程程序更加高效和安全。重点是搭配互斥锁、正确使用等待和通知机制,并注意边界情况。不复杂但容易忽略细节。









