Semaphore 和 SemaphoreSlim

System.Threading.Semaphore 類別表示具名 (全系統) 或區域號誌 (Semaphore)。 它是 Win32 號誌物件周圍的小型包裝函式。 Win32 號誌是計數的號誌,可以用來控制對資源集區的存取。

SemaphoreSlim 類別表示輕量型快速號誌,可在等候時間應該非常短暫時,用於在單一處理序中等候。 SemaphoreSlim 會盡可能仰賴 Common Language Runtime (CLR) 所提供的同步處理原始物件。 不過,它也會在必要時提供延遲初始化的核心架構等候控制代碼,以便支援在多個號誌上等候。 SemaphoreSlim 也支援使用取消語彙基元,不過它不支援具名號誌或使用等候控制代碼進行同步處理。

管理有限的資源

執行緒會呼叫繼承自 WaitHandle 類別的 WaitOne 方法,以進入號誌。 當呼叫傳回時,號誌上的計數便會減少。 當執行緒要求進入,計數卻為零時,執行緒就會遭到封鎖。 當執行緒呼叫 Semaphore.Release 方法以釋放號誌之後,就會允許封鎖的執行緒進入。 要進入號誌的封鎖執行緒並沒有固定的順序,例如先進先出 (FIFO) 或後進先出 (LIFO)。

一個執行緒可以藉由重複呼叫 WaitOne 方法,進入號誌多次。 若要釋放號誌,執行緒可以用相同次數呼叫 Release() 方法多載,或是呼叫 Release(Int32) 方法多載,並指定要釋放的進入次數。

號誌和執行緒識別

Semaphore 類別並不會在對 WaitOneRelease 方法的呼叫上,強制執行緒識別 (Identity)。 例如,號誌的常見使用案例都會涉及一個產生者執行緒和一個消費者執行緒,而且其中一個執行緒會始終遞增號誌計數,另一個則會始終遞減計數。

程式設計人員的責任,是要確定執行緒不會釋放號誌太多次。 例如,假設某個號誌的最大計數為 2,而且執行緒 A 和執行緒 B 兩者都進入了該號誌。 如果執行緒 B 發生程式設計錯誤,導致呼叫 Release 兩次,那麼兩次呼叫都會成功。 此時在號誌上的計數已滿,因此執行緒 A 後來呼叫 Release 時,就會擲回 SemaphoreFullException

具名號誌

Windows 作業系統允許號誌具有名稱。 具名號誌是全系統的。 也就是說,一旦建立具名號誌,所有處理序中的所有執行緒都可以看見該號誌。 因此,具名號誌可以用來對處理序及執行緒的活動進行同步處理。

使用指定名稱的其中一個建構函式 (Constructor),即可建立表示具名系統號誌的 Semaphore 物件。

注意事項注意事項

由於具名號誌是全系統的,因此可能會出現具有多個表示相同具名號誌的 Semaphore 物件。每當您呼叫建構函式或 Semaphore.OpenExisting 方法時,都會建立新的 Semaphore 物件。重複指定相同的名稱,便會建立多個表示相同具名號誌的物件。

當您使用具名號誌時,請特別注意。 由於具名號誌是全系統的,使用相同名稱的另一個處理序可能會意外地進入您的號誌。 在同一部電腦上執行的惡意程式碼,可能會利用這點發動拒絕服務攻擊。

請使用存取控制項安全性來保護表示具名號誌的 Semaphore 物件,並且最好使用會指定 System.Security.AccessControl.SemaphoreSecurity 物件的建構函式。 您也可以使用 Semaphore.SetAccessControl 方法來套用存取控制項安全性,不過這樣會在建立號誌之後,以及號誌得到保護之前,形成具有弱點的一段時間。 以存取控制項安全性來保護號誌,有助於防止惡意攻擊,但是並不能解決意外名稱衝突的問題。

請參閱

參考

Semaphore

SemaphoreSlim

其他資源

執行緒處理物件和功能