C++條件變量


一、有什么用:

當需要死循環判斷某個條件成立與否時【true or false】,我們往往需要開一個線程死循環來判斷,這樣非常消耗CPU。使用條件變量,可以讓當前線程wait,釋放CPU,如果條件改變時,我們再notify退出線程,再次進行判斷。

二、其他解釋

想要修改共享變量(即“條件”)的線程必須:
1. 獲得一個std::mutex
2. 當持有鎖的時候,執行修改動作
3. 對std::condition_variable執行notify_one或notify_all(當做notify動作時,不必持有鎖)

即使共享變量是原子性的,它也必須在mutex的保護下被修改,這是為了能夠將改動正確發布到正在等待的線程。

任意要等待std::condition_variable的線程必須:
1. 獲取std::unique_lock<std::mutex>,這個mutex正是用來保護共享變量(即“條件”)的
2. 執行wait, wait_for或者wait_until. 這些等待動作原子性地釋放mutex,並使得線程的執行暫停
3. 當獲得條件變量的通知,或者超時,或者一個虛假的喚醒,那么線程就會被喚醒,並且獲得mutex. 然后線程應該檢查條件是否成立,如果是虛假喚醒,就繼續等待。

【注: 所謂虛假喚醒,就是因為某種未知的罕見的原因,線程被從等待狀態喚醒了,但其實共享變量(即條件)並未變為true。因此此時應繼續等待】

 https://en.cppreference.com/w/cpp/thread/condition_variable

三、代碼

std::deque<int> q;
std::mutex mu;
std::condition_variable cond;

void function_1() //生產者 { int count = 10; while (count > 0) { std::unique_lock<std::mutex> locker(mu); q.push_front(count); locker.unlock(); cond.notify_one(); // Notify one waiting thread, if there is one. std::this_thread::sleep_for(std::chrono::seconds(1)); count--; } } void function_2() //消費者 { int data = 0; while (data != 1) { std::unique_lock<std::mutex> locker(mu); while (q.empty()) cond.wait(locker); // Unlock mu and wait to be notified data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } } int main() { std::thread t1(function_1); std::thread t2(function_2); t1.join(); t2.join(); return 0; }

 

核心:

①、在消費者里判斷隊列是否為空后,如果不為空則wait,等待生產者發送notify信號

②、在生產者那里,如果生產了任務,則發送notify信號,告訴消費者可以試圖退出wait,判斷隊列是否為空,如果有任務則調度處理任務,如果還是空則說明此次notify是錯誤的,可能是其他地方發出來干擾的,生產者繼續wait。

③、流程:

軟件開啟,生成消費者線程消費隊列,應該是一個while循環,在循環里獲取鎖,再來一個while循環判斷條件,如果條件不成立則wait,wait會自動釋放鎖;

此時消費者已經沒有鎖了,在生產者線程里,獲取鎖,然后往里面加任務,退出作用域釋放鎖,然后notify告知消費者退出wait,消費者重新獲取鎖,然后從隊列里取任務;

整個過程,生產者加任務時生產者持有鎖,消費者取任務時消費者持有鎖。

 

對於此處補充:https://www.cnblogs.com/judes/p/11132918.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM