信號量(Semaphore)
Semaphore 一般譯作 信號量
,它也是一種線程同步工具,主要用於多個線程對共享資源進行並行操作的一種工具類。它代表了一種許可
的概念,是否允許多線程對同一資源進行操作的許可,使用 Semaphore 可以控制並發訪問資源的線程個數。
Semaphore 的使用場景
它與的互斥鎖區別是 互斥鎖:是線程間互斥用的,一個線程占用了某一個共享資源,那么別的線程就無法訪問,直到這個線程離開,其他的線程才開始可以使用這個共享資源。可以把互斥鎖看成二值信號量。
引發的問題
優先級反轉,是指在使用信號量時,可能會出現的這樣一種不合理的現象,即:
高優先級任務被低優先級任務阻塞,導致高優先級任務遲遲得不到調度。但其他中等優先級的任務卻能搶到CPU資源。-- 從現象上來看,好像是中優先級的任務比高優先級任務具有更高的優先權。
具體來說:當高優先級任務正等待信號量(此信號量被一個低優先級任務擁有着)的時候,一個介於兩個任務優先之間的中等優先級任務開始執行——這就會導致一個高優先級任務在等待一個低優先級任務,而低優先級任務卻無法執行類似死鎖的情形發生。
主要方法
Semaphore(1, 4):默認運行信號量之后就可以釋放一條線程進入臨界資源。手動設置Release的一次最大個數是4條線程,臨界區最大的線程數是4.當一次釋放的線程超過等待的資源數就會報錯
WaitOne()阻塞線程,等燈來
Release(N) 同時放行條線程進入資源區,最大不能超過初始化設定的maximumCount
Close()釋放所有
使用方式1
有10個線程,同時只執行4條線程,每完成一個就Release一個,等待中的就補上去
代碼如下:
該代碼會正常執行完成,並且釋放所有線程,因為初始化話new Semaphore(1, 4)時候已經設置默認釋放一條線程,這條線程執行完成后road.Release();又釋放下一條。依次釋放完所有線程。
Semaphore road = new Semaphore(1, 4); for(int i = 0; i < 10; i++) { new Thread(obj => { int se = (int)obj; Console.WriteLine(se); road.WaitOne(); Console.WriteLine("release{0}",obj); road.Release();//該線程執行完畢,后再釋放一個線程 } ).Start(i); } Thread.Sleep(1000); //該代碼會正常執行完成,並且釋放說有線程,因為初始化話new Semaphore(1, 4)時候已經設置默認釋放一條線程,這條線程執行完成后road.Release();又釋放下一條。依次釋放完所有線程。
另外,信號量是內核對象可以再多個進程中使用。可以給信號量設置一個名稱,這個名稱是操作系統可見的,因此,可以使用這些信號量來協調跨進程邊界的資源使用。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Semaphore2 { class Program { static void Main(string[] args) { Semaphore seamphore = new Semaphore(5, 5, "SemaphoreExample"); seamphore.WaitOne(); Console.WriteLine("Seamphore 1"); seamphore.WaitOne(); Console.WriteLine("Seamphore 2"); seamphore.WaitOne(); Console.WriteLine("Seamphore 3"); Console.ReadLine(); seamphore.Release(3); } } } 復制代碼
運行兩個這樣的程序,你將看到這樣的結果,在第二個運行的示例中,會將線程阻塞在第三個信號量