std::condition_variable
是 C++ 标准库中用于线程同步的工具之一,它允许一个或多个线程等待某个条件的发生。std::condition_variable
通常与互斥锁(std::mutex
)一起使用,以实现线程间的同步和通信。
一、基本概念
std::condition_variable
的主要功能是允许线程在某个条件不满足时进入休眠状态,并在条件满足时被唤醒。它通常用于实现生产者-消费者模式、线程间同步等场景。
二、工作原理
- 互斥锁(Mutex):
std::condition_variable
需要与一个互斥锁(std::mutex
)一起使用,以确保线程安全。- 互斥锁用于保护共享资源,防止多个线程同时访问。
- 等待条件(Wait):
- 线程可以通过
wait
或wait_for
方法进入休眠状态,直到条件变量被通知(notify
)。 wait
方法会释放互斥锁,并使线程进入休眠状态,直到条件变量被通知。wait_for
方法会释放互斥锁,并使线程进入休眠状态,直到条件变量被通知或超时。
- 通知条件(Notify):
- 通过
notify_one
或notify_all
方法通知等待的线程。 notify_one
唤醒一个等待的线程。notify_all
唤醒所有等待的线程。
三、示例代码
以下是一个简单的生产者-消费者示例,展示如何使用 std::condition_variable
实现线程间的同步。
生产者-消费者示例
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::queue<int> dataQueue;
std::mutex mtx;
std::condition_variable cv;
bool done = false;
void producer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
dataQueue.push(i);
lock.unlock();
cv.notify_one(); // 通知消费者
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟生产时间
}
{
std::unique_lock<std::mutex> lock(mtx);
done = true;
}
cv.notify_all(); // 通知所有消费者
}
void consumer(int id) {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !dataQueue.empty() || done; }); // 等待条件
if (done && dataQueue.empty()) {
break; // 如果生产者完成且队列为空,退出
}
int data = dataQueue.front();
dataQueue.pop();
lock.unlock();
std::cout << "Consumer " << id << " processed data: " << data << std::endl;
}
}
int main() {
std::thread producerThread(producer);
std::thread consumerThread1(consumer, 1);
std::thread consumerThread2(consumer, 2);
producerThread.join();
consumerThread1.join();
consumerThread2.join();
return 0;
}
四、关键点解释
- 互斥锁(Mutex):
std::mutex mtx
用于保护共享资源dataQueue
,防止多个线程同时访问。
- 条件变量(Condition Variable):
std::condition_variable cv
用于线程间的同步,允许线程在条件不满足时进入休眠状态。
- 等待条件(Wait):
cv.wait(lock, [] { return !dataQueue.empty() || done; });
释放互斥锁并使线程进入休眠状态,直到条件变量被通知。cv.wait
的第二个参数是一个谓词,用于检查条件是否满足。如果条件不满足,线程将继续休眠。
- 通知条件(Notify):
cv.notify_one();
唤醒一个等待的线程。cv.notify_all();
唤醒所有等待的线程。
五、注意事项
- 避免死锁:
- 确保在调用
wait
或wait_for
之前已经锁定了互斥锁。 - 确保在通知条件变量之前释放互斥锁。
- 避免虚假唤醒:
- 使用谓词来检查条件是否真正满足,避免虚假唤醒导致的逻辑错误。
- 线程安全:
- 确保所有对共享资源的访问都在互斥锁的保护下进行。
六、总结
std::condition_variable
是 C++ 标准库中用于线程同步的强大工具。通过与互斥锁(std::mutex
)一起使用,可以实现线程间的高效同步和通信。在生产者-消费者模式、线程间同步等场景中,std::condition_variable
提供了简洁且高效的解决方案。