C#多線程--信號量(Semaphore)

百度百科:Semaphore,是負責協調各個線程, 以保證它們可以正確、合理的使用公共資源。也是操做系統中用於控制進程同步互斥的量。html

Semaphore經常使用的方法有兩個WaitOne()Release(),Release()的做用是退出信號量並返回前一個計數,而WaitOne()則是阻止當前線程,直到當前線程的WaitHandle 收到信號。這裏我舉一個例子讓你們更容易理解:當咱們這樣實例化Semaphore時候多線程

Semaphore sema = new Semaphore(x,y)

有一隊人排隊上洗手間,人就至關於線程,x爲還剩餘的位置數量,y爲總的位置數量。併發

WaitOne()方法就至關於人在等待洗手間位置的行爲,而Release()方法就至關於一我的從洗手間出來的行爲,這裏再假設x和y都爲5,說明開始的時候洗手間有5個空位置,且總共只有5個位置,當一隊超過5我的的隊伍要上洗手間的就排隊,首先WaitOne()方法等待,發現有空位就依次進去,每進去一個空位減一,直到進去5以後個沒有空位,這時候後面的人就一直等待,直到進去的人從洗手間出來Release()方法,空位加一,在等待WaitOne()方法的人發現有空位又進去一個空位減一……如此循環往復。spa

請看下面例子:操作系統

public class Program
    {
        static Semaphore sema = new Semaphore(5, 5);
        const int cycleNum = 9;
        static void Main(string[] args) 
        {
            for(int i = 0; i < cycleNum; i++)
            {
                Thread td = new Thread(new ParameterizedThreadStart(testFun));
                td.Name = string.Format("編號{0}",i.ToString());
                td.Start(td.Name);
            }
            Console.ReadKey();
        }
        public static void testFun(object obj)
        {
            sema.WaitOne();
            Console.WriteLine(obj.ToString() + "進洗手間:" + DateTime.Now.ToString());
            Thread.Sleep(2000);
            Console.WriteLine(obj.ToString() + "出洗手間:" + DateTime.Now.ToString());
            sema.Release();
        }
    }

運行結果以下:線程

image

這裏我要說明一點,信號量控制的只是線程同步的量,而無論順序,這個例子來講線程控制的就是線程同步量爲5,也就是同時併發的線程數量爲5個,至因而哪一個先哪一個後不是由這裏的信號量決定的。code

固然這個例子中因沒有作什麼複雜的操做,通常狀況進入線程的時間和每一個線程要的時間不會有太大差異,因此執行的順序仍是很規律的(爲了說明這個問題我也是運行了屢次才讓結果稍有不一樣,這裏編號2搶在了編號1前面就是這個道理),若是線程中有很複雜的操做每一個線程在運行中所用的時間有比較大的差異,或者循環開始有複雜操做那麼極可能就不是編號0先進入洗手間了,且不必定是先進入的就會先出來。orm

接下來再簡單介紹一下Semaphore的WaitOne()和Release()的重載方法htm

public int Release(int releaseCount);

releaseCount指的是釋放的信號量數量,若是沒有參數默認爲1,Release()就至關於Release(1)blog

這裏要說明一點,當Release()或者Release(int releaseCount)執行時致使信號量計數大於最大數量時會拋出SemaphoreFullException異常。下面這種狀況就會異常:

Semaphore sem = new Semaphore(4,5);
sem.Release(2);//這裏是釋放2個信號量加上以前的4個,超出5個了

 

public virtual bool WaitOne(TimeSpan timeout);
public virtual bool WaitOne(int millisecondsTimeout);

第一個重載參數timeout:指定時間間隔,若在這段時間內沒有接收到信號則跳過等待繼續執行

第二個重載參數millisecondsTimeout:指定時間間隔整數毫秒,若在這段時間內沒有接收到信號則跳過等待繼續執行

WaitOne()還有兩個重載方法不是很經常使用這裏就不介紹了。上面的重載方法這裏也再也不進了案例說明了,有興趣的朋友能夠本身嘗試一下。

做者:依封劍白
出處:C#多線程--信號量(Semaphore)本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。若有問題或建議,請多多賜教,很是感謝。

相關文章
相關標籤/搜索