上一篇咱們介紹了互斥體,這一篇介紹信號量。。。。。。。。。。。。函數
1、什麼是信號量?spa
信號量對象對線程的同步方式與前面幾種方法不一樣,信號容許多個線程同時使用共享資源,這與操做系統中的PV操做相同。它指出了同時訪問共享資源的線程最大數目。它容許多個線程在同一時刻訪問同一資源,可是須要限制在同一時刻訪問此資源的最大線程數目。在建立信號量時即要同時指出容許的最大資源計數和當前可用資源計數。通常是將當前可用資源計數設置爲最大資源計數,每增長一個線程對共享資源的訪問,當前可用資源計數就會減1,只要當前可用資源計數是大於0的,就能夠發出信號量信號。可是當前可用計數減少到0時則說明當前佔用資源的線程數已經達到了所容許的最大數目,不能在容許其餘線程的進入,此時的信號量信號將沒法發出。線程在處理完共享資源後,應在離開的同時經過ReleaseSemaphore()函數將當前可用資源計數加1。在任什麼時候候當前可用資源計數決不可能大於最大資源計數。操作系統
信號量有一個使用計數器,這個使用計數器,是信號量的最大資源計數和當前資源計數的差值。線程
2、信號量的使用原理? code
a、若是當前資源計數大於0,那麼信號量處於觸發狀態。orm
b、若是當前資源計數等於0,那麼信號量處於未觸發狀態。對象
c、系統絕對不會讓當前資源計數變爲負數。blog
d、當前資源計數絕對不會大於最大最大資源計數進程
3、示例 事件
一、線程間的sempahore同步
若是出現 WaitOne 就一個要有對應的Release 即獲取信號量後,必定要釋放。
如:6個進程須要同時使用打印機,而電腦上只有四臺打印機,則打印機是被保護的資源,信號量爲4。則須要用semaphore來同步。
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SemaphoreClass { class Program { static void Main(string[] args) { int sourceCount = 4;//打印機數量 int threadCount = 6;//須要打印的線程數目 // maximumCount-initialCount 之間的差值爲已經鎖定的 semaphore的數量(即信號量使用計數器) 此實例中已經指定佔用了0個信號量 //Semaphore的第三個參數爲信號量的名稱,若是設定了名稱,則可用於進程間的同步,若是沒有設置名稱則只能用於進程內的線程同步 Semaphore sempaphore = new Semaphore(sourceCount, sourceCount, "sempaphore"); Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { threads[i] = new Thread(ThreadMain); threads[i].Start(sempaphore); } for (int i = 0; i < threadCount; i++) { threads[i].Join(); } Console.WriteLine("All threads finished!"); Console.ReadKey(); } /// <summary> /// 線程執行的方法 /// </summary> /// <param name="o"></param> static void ThreadMain(object o) { Semaphore semaphore = o as Semaphore; Trace.Assert(semaphore != null, "o must be a semphore type"); bool isCompleted = false; while (!isCompleted) { //鎖定信號量,若是鎖定計數已經達到最高計數限制,則等待600毫秒。若是在600毫秒後未能得到鎖定,則返回false。 if (semaphore.WaitOne(600, false)) { try { Console.WriteLine("Thread {0} locks the semaphore ", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(2000); } finally { //解除資源的鎖定。參數爲退出信號量的次數。佔用一個信號量故退出一個。 semaphore.Release(1); Console.WriteLine("Thread {0} release the semaphore", Thread.CurrentThread.ManagedThreadId); isCompleted = true; } } else { Console.WriteLine("Timeot for thread {0}; wait again", Thread.CurrentThread.ManagedThreadId); } } } } }
二、進程間的sempahore同步
下面的例子將使用信號量來同步進程,一個應用程序能夠有二個實例運行(若是隻容許有一個實例來運行,最優之選是mutex,其次纔是信號量)。雖然這個例子不太實用,但徹底能夠說明semaphore的特性。
注意:生成解決方案後運行三次生成EXE,就會看到結果。信號量的進程同步和信號量的應用程序的名稱無關。只要使用了一樣名稱的信號量,他們以前就存在了一種協約。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SemaphoreProcess { class Program { static void Main(string[] args) { //定義可同步運行的可用實例數 int CreateNew = 2; //定義可同步運行的最大實例數 int MaxCreateNew = 5; // maximumCount-initialCount 之間的差值爲已經鎖定的 semaphore的數量 此實例中已經指定佔用了3個信號量 計算方式爲(MaxCreateNew-CreateNew) //Semaphore的第三個參數爲信號量的名稱,若是設定了名稱,則可用於進程間的同步,若是沒有設置名稱則只能用於進程內的線程同步 System.Threading.Semaphore sempaphore = new System.Threading.Semaphore(CreateNew, MaxCreateNew, "sempaphoreProcess"); if (sempaphore.WaitOne(100, false)) { Console.WriteLine("系統正在運行……"); Console.ReadKey(); } else { MessageBox.Show("當前已經有 " + CreateNew + " 個實例在運行,系統將退出!", "您好", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } }
下一篇介紹事件。。。。。。。。。。。。