std::counting_semaphore, std::binary_semaphore
| 定義於標頭檔案 <semaphore> |
||
| template< std::ptrdiff_t LeastMaxValue = /* implementation-defined */ > class counting_semaphore; |
(1) | (C++20 起) |
| using binary_semaphore = std::counting_semaphore<1>; |
(2) | (C++20 起) |
counting_semaphore 是一種輕量級的同步原語,可以控制對共享資源的訪問。與 std::mutex 不同,counting_semaphore 允許超過一個併發訪問同一資源,至少 LeastMaxValue 個併發訪問器。如果 LeastMaxValue 為負,則程式格式錯誤。binary_semaphore 是 std::counting_semaphore 的特化別名,其 LeastMaxValue 為 1。實現可以比 std::counting_semaphore 的預設實現更高效地實現 binary_semaphore。一個 counting_semaphore 包含一個由建構函式初始化的內部計數器。此計數器在呼叫 acquire() 和相關方法時遞減,並在呼叫 release() 時遞增。當計數器為零時,acquire() 阻塞直到計數器遞增,但 try_acquire() 不阻塞;try_acquire_for() 和 try_acquire_until() 阻塞直到計數器遞增或達到超時。
類似於 std::condition_variable::wait(),counting_semaphore 的 try_acquire() 可能會虛假失敗。
std::counting_semaphore 的特化不是 可預設構造的 (DefaultConstructible)、可複製構造的 (CopyConstructible)、可移動構造的 (MoveConstructible)、可複製賦值的 (CopyAssignable) 或 可移動賦值的 (MoveAssignable)。
目錄 |
[編輯] 資料成員
| 成員名稱 (Member name) | 定義 |
counter (私有) |
型別為 std::ptrdiff_t 的內部計數器。 (僅用於闡釋的成員物件*) |
[編輯] 成員函式
構造一個 counting_semaphore(公共成員函式) | |
銷燬 counting_semaphore(公共成員函式) | |
| operator= [已刪除] |
counting_semaphore 不可賦值(公共成員函式) |
操作 | |
| 增加內部計數器並解除阻塞獲取器 (公共成員函式) | |
| 遞減內部計數器或阻塞直到可以遞減 (公共成員函式) | |
| 嘗試遞減內部計數器而不阻塞 (公共成員函式) | |
| 嘗試遞減內部計數器,阻塞一段持續時間 (公共成員函式) | |
| 嘗試遞減內部計數器,阻塞直到某一時間點 (公共成員函式) | |
常量 | |
| [靜態] |
返回內部計數器的最大可能值 (公共靜態成員函式) |
[編輯] 註解
正如其名稱所示,LeastMaxValue 是*最小*最大值,而不是*實際*最大值。因此 max() 可能返回大於 LeastMaxValue 的數字。
與 std::mutex 不同,counting_semaphore 不與執行執行緒繫結——例如,獲取訊號量可以在與釋放訊號量不同的執行緒上發生。所有對 counting_semaphore 的操作都可以併發執行,並且與特定的執行執行緒沒有任何關係,除了解構函式不能併發執行但可以在不同執行緒上執行。
訊號量也常用於信令/通知而不是互斥的語義,透過將訊號量初始化為 0,從而阻塞嘗試 acquire() 的接收者,直到通知者透過呼叫 release(n) 來“發出訊號”。在這方面,訊號量可以被視為 std::condition_variable 的替代方案,通常具有更好的效能。
| 特性測試宏 | 值 | 標準 | 特性 |
|---|---|---|---|
__cpp_lib_semaphore |
201907L |
(C++20) | std::counting_semaphore, std::binary_semaphore |
[編輯] 示例
#include <chrono> #include <iostream> #include <semaphore> #include <thread> // global binary semaphore instances // object counts are set to zero // objects are in non-signaled state std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // wait for a signal from the main proc // by attempting to decrement the semaphore smphSignalMainToThread.acquire(); // this call blocks until the semaphore's count // is increased from the main proc std::cout << "[thread] Got the signal\n"; // response message // wait for 3 seconds to imitate some work // being done by the thread using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // message // signal the main proc back smphSignalThreadToMain.release(); } int main() { // create some worker thread std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // message // signal the worker thread to start working // by increasing the semaphore's count smphSignalMainToThread.release(); // wait until the worker thread is done doing the work // by attempting to decrement the semaphore's count smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // response message thrWorker.join(); }
輸出
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal