等待乙個時間或其他條件
在乙個執行緒等待完成任務時,會有很多選擇:
1. 它可以持續的檢查共享資料標誌(用於做保護工作的互斥量),直到另乙個執行緒完成工作時對這個標誌進行重設。缺點:資源浪費,開銷大
2. 在等待執行緒的檢查間隙,使用std::this_thread::sleep_for()進行週期性的間歇。 缺點:休眠時間抉擇困難
boolflag;
std::mutex m;
void
wait_for_flag()
}
3. 使用c++標準庫提供的工具去等待事件的發生。通過另一線程觸發等待事件的機制是最基本的喚醒方式,這種機制就稱為「條件變數」。
c++標準庫對條件變數有兩套實現:std::condition_variable
和std::condition_variable_any
。這兩個實現都包含在標頭檔案的宣告中。兩者都需要與乙個互斥量一起才能工作(互斥量是為了同步)
std::condition_variable:只能與std::mutex一起工作,開銷少
std::condition_variable_any:可以和任何滿足最低標準的互斥量一起工作,開銷大
std::condition_variable 提供兩個重要的介面:notify_one()
和wait()。wait()
可以讓執行緒陷入休眠狀態,notify_one()
就是喚醒處於wait
中的其中乙個條件變數(可能當時有很多條件變數都處於wait
狀態)。
templatewait(std::unique_lock& lk, predicate pred)
wait()會去檢查這些條件(通過呼叫所提供的函式),當條件滿足(呼叫所提供的函式返回true)時返回。如果條件不滿足(呼叫所提供的函式返回false),wait()函式將解鎖互斥量,並且將這個執行緒置於阻塞或等待狀態。另外乙個執行緒呼叫notify_one()通知條件變數時,執行緒從睡眠狀態中甦醒,重新獲取互斥鎖,並且再次檢查條件是否滿足。
std::condition_variable::wait的乙個最小化實現:
templatevoid minimal_wait(std::unique_lock&lk,predicate pred)}
考慮乙個生產者消費者模型:乙個執行緒往佇列中放入資料,乙個執行緒往佇列中取資料,取資料前需要判斷一下佇列中確實有資料,由於這個佇列是執行緒間共享的,所以,需要使用互斥鎖進行保護,乙個執行緒在往佇列新增資料的時候,另乙個執行緒不能取,反之亦然。用互斥鎖實現如下:
#include #include#include
#include
std::deque
q;std::mutex mu;
void
function_1()
}void
function_2()
else
}}int
main()
問題在於,如果生產者的速度比較慢,**中每隔1s才會有一次資料生產,這時消費者都要去獲取鎖-->判斷佇列裡是否有資料-->釋放鎖,這個過程就是資源的浪費,無用功使得cpu佔用率很高。
使用std::this_thread::sleep_for()來對**進行改造:
voidfunction_2()
else
}}
這樣可以減低cpu佔用率,但問題在於在實際操作中如何選擇休眠時間,太長或者太短都不好。
最後可以使用條件變數來對這個**進行改造:
#include #include#include
#include
#include
std::deque
q;std::mutex mu;
std::condition_variable cond;
void
function_1()
}void
function_2() ); //
unlock mu and wait to be notified
data =q.back();
q.pop_back();
locker.unlock();
std::cout
<< "
t2 got a value from t1:
"<< data <}
}int
main()
需要注意的幾點:
在配合條件變數使用鎖時,使用std::unique_lock比std::lock_guard合適,因為在wait內部有對鎖的unlock和lock操作
使用細粒度鎖,盡量減小鎖的範圍,在notify_one()
的時候,不需要處於互斥鎖的保護範圍內,所以在喚醒條件變數之前可以將鎖unlock()
。
多執行緒(併發)學習筆記
1,無論以哪種方式啟動乙個執行緒,要給執行緒乙個名字,對排錯 監控有幫助。2,要對執行緒interrupt做處理。3,futrure 是任務的提交者和執行者之間的通訊手段,get 會阻塞 executorservice executor executors.newsinglethreadexecut...
C 多執行緒學習2
include stdafx.h include beginthread.h ifdef debug define new debug new undef this file static char this file file endif include stdafx.h include wind...
C C 筆記 2 多執行緒 併發 互斥鎖
1.1 執行緒的管理 乙個程序中至少存在乙個執行緒,這個執行緒被稱為主線程,我們可以在任意執行緒中建立執行緒類的例項。每個執行緒都需要乙個入口函式,當入口函式返回時,執行緒就會退出,主線程的入口函式為main 1.1.1 執行緒的啟動 執行緒的建立十分簡單,我們只需建立乙個執行緒類的例項,並為它傳入...