0. 引言
在這一章,主要介紹條件變量,期望(future),屏障等,並且也會給出相應的使用方式。
1. 等待某個事件或者條件
首先考慮這樣一個場景,你正在坐火車去找你對象,爲了不錯過,你會怎麼辦呢?一般我們會要麼一夜不睡覺,自己檢查每一站看看是不是到達了對象的城市的火車站,或者我們會定個鬧鐘,當快到站的時候叫醒我們,但是鬧鐘可能會出錯,所以你也可能錯過站,當然如果你有一個小夥伴,在到站的時候能叫醒你,這樣你就可以安心休息了,但是你小夥伴就累了。好了,那麼這個場景如何應用到多線程呢?
如果一個線程需要等待另一個線程完成某個任務才能執行,此時如何在兩個線程間進行操作的同步呢?
參考我們上述坐火車找對象的場景,等待線程計作A,其他線程計作B,其同步操作的解決方案有設置flag,設置鬧鐘,以及條件變量。
設置flag:
在線程A中檢查flag是否被設置(該flag由mutex)表示,flag會由線程B設置。 該方案有兩個缺點:第一,當A在重複檢測flag時相當於polling,浪費CPU時間;第二,當在檢測flag時,mutex會被上鎖,這樣B無法獲得該鎖,阻礙了B設置flag的時間。
設置鬧鐘:
利用std::this_thread::sleep_for()函數設置一個鬧鐘,讓線程A休眠,當鬧鐘時間到了後在檢查flag,看看是否到達目的地,下面看一個例子
#include <mutex>
#include <thread>
#include <chrono>
bool flag;
std::mutex mut;
using chrono = std::chrono;
void wait_for_flag() {
std::unique_lock<std::lock> lt(mut);
while (!flag) {
lt.unlock();
std::this_thread::sleep_for(chrono::milliseconds(100));
lt.lock();
}
}
設置鬧鐘這種解決辦法,相對於設置flag方案有一定的提升,因爲sleep線程A,可以提升CPU的利用率,但該方案的缺點是設置的鬧鐘長度並非是完全理想的。
條件變量:
C++標準庫中提供了std::condition_variable 去更優的通知某個線程其等待的事件完成
1.1 等待條件變量