1. 程式人生 > 程式設計 >深入瞭解c# 訊號量和互斥體

深入瞭解c# 訊號量和互斥體

一、訊號量(Semaphore)

訊號量(Semaphore)是由核心物件維護的int變數,當訊號量為0時,在訊號量上等待的執行緒會堵塞,訊號量大於0時,就解除堵塞。當在一個訊號量上等待的執行緒解除堵塞時,核心自動會將訊號量的計數減1。在.net 下通過Semaphore類來實現訊號量同步。

Semaphore類限制可同時訪問某一資源或資源池的執行緒數。WaitOne method,which is inherited from the WaitHandle class,and release the semaphore by calling the Release method.">執行緒通過呼叫 WaitOne方法將訊號量減1,並通過呼叫 Release方法把訊號量加1。

先說下建構函式:

public Semaphore(int initialCount,int maximumCount);通過兩個引數來設定訊號的初始計數和最大計數。

下面通過一段程式碼來演示訊號量同步的使用:

 class Program
  {
    // 初始訊號量計數為0,最大計數為10
    public static Semaphore semaphore =new Semaphore(0,10);
    public static int time = 0;
    static void Main(string[] args)
    {
      for (int i = 0; i < 5; i++)
      {
        Thread test = new Thread(new ParameterizedThreadStart(TestMethod));

        // 開始執行緒,並傳遞引數
        test.Start(i);
      }

      // 等待1秒讓所有執行緒開始並阻塞在訊號量上
      Thread.Sleep(500);

      // 訊號量計數加4
      // 最後可以看到輸出結果次數為4次
      semaphore.Release(4);
      Console.Read();     
    }

    public static void TestMethod(object number)
    {
      // 設定一個時間間隔讓輸出有順序
      int span = Interlocked.Add(ref time,100);
      Thread.Sleep(1000 + span);

      //訊號量計數減1
      semaphore.WaitOne();

      Console.WriteLine("Thread {0} run ",number);
    }
  }

執行結果:

深入瞭解c# 訊號量和互斥體

同樣訊號量也可以實現程序中執行緒的同步,同樣也是通過對訊號量命名來實現的,

通過呼叫public Semaphore(int initialCount,int maximumCount,string name);該建構函式多傳入一個訊號量名來實現

下面一段例項程式碼來演示下:

using System;
using System.Threading;

namespace SemaphoreSample
{
  class Program
  {
    // 初始訊號量計數為4,最大計數為10
    public static Semaphore semaphore =new Semaphore(4,10,"My");
    public static int time = 0;
    static void Main(string[] args)
    {
      for (int i = 0; i < 3; i++)
      {
        Thread test = new Thread(new ParameterizedThreadStart(TestMethod));

        // 開始執行緒,並傳遞引數
        test.Start(i);
      }

      // 等待1秒讓所有執行緒開始並阻塞在訊號量上
      Thread.Sleep(1000);

      Console.Read();     
    }

    public static void TestMethod(object number)
    {
      // 設定一個時間間隔讓輸出有順序
      int span = Interlocked.Add(ref time,500);
      Thread.Sleep(1000 + span);

      //訊號量計數減1
      semaphore.WaitOne();

      Console.WriteLine("Thread {0} run ",number);
    }
  }
}

執行結果:

深入瞭解c# 訊號量和互斥體

從執行結果中可以看出, 第二個程序值運行了一行語句, 因為我們設定的初始訊號計數為4,每執行一個執行緒,訊號計數通過呼叫WaitOne方法減1,所以第二個進行一開始訊號計數為1而不是程序一中的4,如果我們把訊號計數後面的name引數去除的話,此時第二個程序和第一個程序中的結果應該是一樣的(因為此時沒有進行不同程序中執行緒的同步)。

二、互斥體(Mutex)

同樣互斥體也是同樣可以實現執行緒之間的同步和不同程序中執行緒的同步的

先看看執行緒之間的同步的例子吧(在這裡我也不多做解釋了,因為他們之間的使用很類似,直接貼出程式碼):

 class Program
  {
    public static Mutex mutex = new Mutex();
    public static int count;

    static void Main(string[] args)
    {
      for (int i = 0; i < 10; i++)
      {
        Thread test = new Thread(TestMethod);

        // 開始執行緒,並傳遞引數
        test.Start();
      }

      Console.Read();
    }

    public static void TestMethod()
    {
      mutex.WaitOne();
      Thread.Sleep(500);
      count++;
      Console.WriteLine("Current Cout Number is {0}",count);
      mutex.ReleaseMutex();
    }
  }

執行結果:

深入瞭解c# 訊號量和互斥體

實現程序間同步:

 class Program
  {
    public static Mutex mutex = new Mutex(false,"My");

    static void Main(string[] args)
    {
      Thread t = new Thread(TestMethod);
      t.Start();

      Console.Read();
    }

    public static void TestMethod()
    {
      mutex.WaitOne();
      Thread.Sleep(5000);
      Console.WriteLine("Method start at : " + DateTime.Now.ToLongTimeString());
      mutex.ReleaseMutex();
    }
  }

執行結果:

深入瞭解c# 訊號量和互斥體

從執行結果看出兩個程序之間的時間間隔為5秒,當我們把建構函式中命名引數去掉時就可以看出差別了。

到這裡多執行緒處理基本上講完,這個系列也只是一個入門,真真要好好掌握多執行緒,還是要在專案中多去實戰的。接下來我可能會做一個小的例子的,大概的思路是實現一個檔案的下載的這樣的例子。如果大家有什麼好的例子來運用多執行緒的知識的話,可以留言給我,我也會盡量去實現(如果不會的話,這樣也可以促使我去學習),實現後也會和大家分享的。

以上就是深入瞭解c# 訊號量和互斥體的詳細內容,更多關於c# 訊號量和互斥體的資料請關注我們其它相關文章!