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