std::condition_variable
在 C++11 中,<condition_variable> 头文件提供了 std::condition_variable 和 std::condition_variable_any 类,用于实现线程间的通知机制,帮助线程在某些条件满足时进行同步。它们通常与 std::mutex 一起使用,以协调线程之间的执行。
1. 基本概念
std::condition_variable 允许线程等待某个条件变量的信号,以便在条件满足时继续执行。线程通过调用 wait 方法进入等待状态,并在条件满足时被唤醒。条件变量通常与互斥锁 (std::mutex) 一起使用,以确保条件检查和修改的原子性。
1.1 std::condition_variable
wait方法: 使线程在条件变量上等待。线程在等待时会释放与之关联的互斥锁,并在条件满足时重新获取锁。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void waitingThread() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; }); // 等待条件满足
std::cout << "Condition satisfied!" << std::endl;
}
void signalingThread() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟工作
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_all(); // 唤醒所有等待线程
}
int main() {
std::thread t1(waitingThread);
std::thread t2(signalingThread);
t1.join();
t2.join();
return 0;
}
notify_one和notify_all方法: 用于唤醒一个或所有等待的线程。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void waitingThread() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; }); // 等待条件满足
std::cout << "Thread woke up!" << std::endl;
}
void signalingThread() {
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one(); // 唤醒一个等待线程
}
int main() {
std::thread t1(waitingThread);
std::thread t2(signalingThread);
t1.join();
t2.join();
return 0;
}
1.2 std::condition_variable_any
std::condition_variable_any 可以与任何类型的锁(如 std::mutex、std::recursive_mutex 等)一起使用。它提供了类似于 std::condition_variable 的功能,但不需要特定类型的锁。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
std::mutex mtx;
std::condition_variable_any cv;
bool ready = false;
void waitingThread() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; }); // 等待条件满足
std::cout << "Condition satisfied!" << std::endl;
}
void signalingThread() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟工作
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_all(); // 唤醒所有等待线程
}
int main() {
std::thread t1(waitingThread);
std::thread t2(signalingThread);
t1.join();
t2.join();
return 0;
}
2. 使用场景
- 线程同步: 当多个线程需要在特定条件下执行任务时,使用
std::condition_variable可以协调它们的执行。 - 生产者-消费者模式: 在生产者-消费者模式中,消费者线程在没有数据可用时等待条件变量,生产者线程在生产数据后通知消费者线程。
3. 最佳实践
-
避免虚假唤醒: 条件变量可能会因虚假唤醒而导致线程被唤醒但条件不满足。总是使用
wait的重载版本,并提供一个谓词函数来检查条件是否满足。cv.wait(lock, [] { return conditionIsMet(); }); -
锁的持有: 确保在调用
wait方法时持有互斥锁,并在notify调用后尽快释放锁。 -
性能考虑: 在多线程应用中,频繁的
notify_all可能会导致性能问题。使用notify_one时,能避免不必要的线程唤醒,减少上下文切换的开销。
4. 总结
std::condition_variable 和 std::condition_variable_any 是 C++11 提供的重要同步工具,用于在线程间传递信号和条件。通过正确使用条件变量,可以实现高效的线程同步,确保线程在特定条件下进行协调和通信。了解和掌握这些工具的使用方法,对于编写健壮的多线程程序至关重要。