C++實現訊號量
阿新 • • 發佈:2021-07-07
背景
實現
程式碼
來自為知筆記(Wiz)
原創不易,轉載請註明出處,謝謝
實現
程式碼
背景
訊號量與條件變數差異對比
- 訊號量存在一個計數,可以反映出當前阻塞在wait上的執行緒數(值小於0),或下次wait不會阻塞的執行緒數;條件變數沒有相應計數
- 訊號量僅能遞增或遞減計數,訊號量每次遞增只能喚醒一個阻塞執行緒;條件變數存在廣播操作,能一次性喚醒所有阻塞執行緒
- 訊號量計數可以被初始化為大於0的數n,代表可訪問資源個數,在後續訪問時wait時,n個執行緒均不會阻塞,可同時訪問資源;條件變數初始化後,執行wait的執行緒將全部阻塞,直到收到通知
- 訊號量遞增一次,便會多一個wait不阻塞的執行緒數(不存在阻塞執行緒時);對於條件變數,當沒有執行緒阻塞在wait時,發出的喚醒訊號將被丟棄,導致先發出喚醒訊號,隨後wait將仍被阻塞,即所謂的喚醒丟失
- 訊號量不存在虛假喚醒問題;條件變數存在虛假喚醒
- 訊號量可單獨使用;條件變數必須需配合mutex一起使用
C++標準庫僅有條件變數,而沒有訊號量,下面實現一個跨平臺訊號量
實現
訊號量最基本的操作有三個
- 初始化決定了wait後可立即執行執行緒數
- 遞減操作SemWait,該操作使訊號量減1,如果減1後變為負數,執行緒會阻塞在SemWait上,否則繼續執行
- 遞增操作SemSignal,該操作使訊號量加1,如果加1後大於等於0,阻塞在SemWait上的執行緒被喚醒
程式碼
#pragma once #include <mutex> #include <condition_variable> class Semaphore final{ public: explicit Semaphore(int iCount = 0); ~Semaphore(); void Signal(); void Wait(); int GetValue(); Semaphore(const Semaphore& rhs) = delete; Semaphore(Semaphore&& rhs) = delete; Semaphore& operator=(const Semaphore& rhs) = delete; Semaphore& operator=(Semaphore&& rhs) = delete; private: std::mutex m_mLock; std::condition_variable m_cConditionVariable; int m_iCount; };
#include "Semaphore.h" Semaphore::Semaphore(int iCount) : m_iCount(iCount){ } Semaphore::~Semaphore(){ } void Semaphore::Signal(){ std::unique_lock<std::mutex> lock(m_mLock); if(++m_iCount >= 0){ m_cConditionVariable.notify_one(); } } void Semaphore::Wait(){ std::unique_lock<std::mutex> lock(m_mLock); --m_iCount; m_cConditionVariable.wait(lock, [this] { return m_iCount >= 0; }); } int Semaphore::GetValue(){ std::unique_lock<std::mutex> lock(m_mLock); return m_iCount; }
來自為知筆記(Wiz)
原創不易,轉載請註明出處,謝謝