C++ 标准库
<condition_variable>
在多线程编程中,线程间的同步是一个非常重要的问题。
C++11 标准引入了
<condition_variable>
头文件,它提供了一种机制,允许线程在某些条件不满足时挂起,直到其他线程通知它们条件已经满足。
condition_variable
是用于线程间同步的一种高级工具,它比使用低级同步原语(如互斥锁和条件变量)更加安全和方便。
condition_variable
是一个类模板,用于在多线程环境中实现线程间的同步。它允许一个或多个线程等待某个条件变为真,而其他线程可以唤醒这些等待的线程。
语法
以下是
condition_variable
的基本语法:
#include <condition_variable>
void notify_one() {
// 唤醒一个等待的线程
}
void notify_all() {
// 唤醒所有等待的线程
}
template <class Mutex>
class condition_variable {
public:
condition_variable();
~condition_variable();
void wait(unique_lock<mutex>& lock);
void wait_for(unique_lock<mutex>& lock, chrono::duration<Rep, Period> const& rel_time);
void wait_until(unique_lock<mutex>& lock, chrono::time_point<Clock, Duration> const& abs_time);
void notify_one() noexcept;
void notify_all() noexcept;
};
实例
下面是一个使用
condition_variable
的简单示例,展示了生产者-消费者问题的基本实现。
示例代码
#include <iostream>#include <condition_variable>#include <mutex>#include <queue>#include <thread>std::mutexmtx;std::condition_variablecv;std::queue<int>product;voidproducer(intid){for(inti=0;i<5;++i){std::unique_lock<std::mutex>lck(mtx);product.push(id*100+i);std::cout<<"Producer "<<id<<" produced "<<product.back()<<std::endl;cv.notify_one();lck.unlock();std::this_thread::sleep_for(std::chrono::milliseconds(100));}}voidconsumer(intid){while(true){std::unique_lock<std::mutex>lck(mtx);cv.wait(lck,[]{return!product.empty();});if(!product.empty()){intprod=product.front();product.pop();std::cout<<"Consumer "<<id<<" consumed "<<prod<<std::endl;}lck.unlock();}}intmain(){std::threadproducers[2];std::threadconsumers[2];for(inti=0;i<2;++i){producers[i]=std::thread(producer, i+1);}for(inti=0;i<2;++i){consumers[i]=std::thread(consumer, i+1);}for(inti=0;i<2;++i){producers[i].join();consumers[i].join();}return0;}
这个程序的输出可能会有所不同,因为它依赖于线程调度。但是,你会看到生产者生产产品,然后消费者消费这些产品。输出将类似于:
Producer 1 produced 100 Producer 2 produced 200 Consumer 1 consumed 100 Producer 1 produced 101 Consumer 2 consumed 200 Producer 2 produced 201 Consumer 1 consumed 101 ...
注意事项
-
使用
condition_variable时,必须确保在等待之前获取互斥锁,并且在唤醒后释放互斥锁。 -
wait、wait_for和wait_until函数都会释放互斥锁,然后在等待期间重新获取它。 -
notify_one唤醒一个等待的线程,而notify_all唤醒所有等待的线程。