名稱空間
變體
操作

std::counting_semaphore, std::binary_semaphore

來自 cppreference.com
< cpp‎ | thread
 
 
併發支援庫
執行緒
(C++11)
(C++20)
this_thread 名稱空間
(C++11)
(C++11)
(C++11)
協同取消
互斥
(C++11)
通用鎖管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
條件變數
(C++11)
訊號量
counting_semaphorebinary_semaphore
(C++20)(C++20)
門閂和屏障
(C++20)
(C++20)
期值
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(C++26)
危險指標
原子型別
(C++11)
(C++20)
原子型別的初始化
(C++11)(C++20 中已棄用)
(C++11)(C++20 中已棄用)
記憶體排序
(C++11)(C++26 中已棄用)
原子操作的自由函式
原子標誌的自由函式
 
 
定義於標頭檔案 <semaphore>
template< std::ptrdiff_t LeastMaxValue = /* implementation-defined */ >
class counting_semaphore;
(1) (C++20 起)
using binary_semaphore = std::counting_semaphore<1>;
(2) (C++20 起)
1) counting_semaphore 是一種輕量級的同步原語,可以控制對共享資源的訪問。與 std::mutex 不同,counting_semaphore 允許超過一個併發訪問同一資源,至少 LeastMaxValue 個併發訪問器。如果 LeastMaxValue 為負,則程式格式錯誤。
2) binary_semaphorestd::counting_semaphore 的特化別名,其 LeastMaxValue1。實現可以比 std::counting_semaphore 的預設實現更高效地實現 binary_semaphore

一個 counting_semaphore 包含一個由建構函式初始化的內部計數器。此計數器在呼叫 acquire() 和相關方法時遞減,並在呼叫 release() 時遞增。當計數器為零時,acquire() 阻塞直到計數器遞增,但 try_acquire() 不阻塞;try_acquire_for()try_acquire_until() 阻塞直到計數器遞增或達到超時。

類似於 std::condition_variable::wait()counting_semaphoretry_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