while(某个条件){//这个条件由另外一个线程来变动,因此就一直循环来检查这个条件,CPU就得不到休息,浪费系统的性能 }
std::unique_lock<std::mutex> lk(m); while(某个条件){//这个条件由另外一个线程来变动,先睡眠一会,等待别的线程变动这个条件,CPU获得了休息,节省了系统的性能 lk.unlock(); sleep(休眠必定的时间); lk.lock(); } //缺点:没法准确知道要休眠多长的时间。休眠时间过长就会致使响应过慢,休眠时间太短,醒来发现条件还没被变动,还得继续休眠。
#include <iostream> #include <mutex> #include <queue> #include <condition_variable> #include <thread> #include <unistd.h>//sleep std::mutex mut; std::queue<int> data_queue;//-------------------① std::condition_variable data_cond; void data_preparation_thread(){ int data = 0; while(true){ data++; std::lock_guard<std::mutex> lk(mut); data_queue.push(data);//-------------------② data_cond.notify_one();//-------------------③ std::cout << "after notify_one" << std::endl; //std::this_thread::sleep_for(1000); sleep(1); } } void data_process_thread(){ while(true){ std::unique_lock<std::mutex> lk(mut);//-------------------④ std::cout << "before wait" << std::endl; data_cond.wait(lk, []{return !data_queue.empty();});//-------------------⑤ std::cout << "after wait" << std::endl; int data = data_queue.front(); std::cout << data << std::endl; data_queue.pop(); lk.unlock();//-------------------⑥ //假设处理数据data的函数process要花费大量时间,因此提早解锁 //process(data); } } int main(){ std::thread t1(data_preparation_thread); std::thread t2(data_process_thread); t1.join(); t2.join(); }
这就是为何使用std::unique_lock而不是std::lock_guard。等待中的线程必须解锁互斥元,并在wait返回true的时候从新锁定这个互斥元,std::lock_guard没有这个功能。若是线程在等待期间不解锁互斥元,把数据压入队列的线程就没法锁定这个互斥元,就没法压入数据,就没法执行notify_one(),因此等待的线程就永远处于等待状态。。。ios
github源代码c++
编译方法:git
g++ -g condition_vari-4.1.cpp -std=c++11 -pthread