互斥量和臨界區非常相似,只有擁有了互斥對象的線程才可以訪問共用資源,而互斥對象只有一個,因此可以保證同一時刻有且僅有一個線程可以訪問共用資源,達到線程同步的目的。 互斥量相對於臨界區更為高級,可以對互斥量進行命名,支持跨進程的線程同步。互斥量是調用的Win32的API對互斥鎖的操作,因此在同一操作系 ...
互斥量和臨界區非常相似,只有擁有了互斥對象的線程才可以訪問共用資源,而互斥對象只有一個,因此可以保證同一時刻有且僅有一個線程可以訪問共用資源,達到線程同步的目的。
互斥量相對於臨界區更為高級,可以對互斥量進行命名,支持跨進程的線程同步。互斥量是調用的Win32的API對互斥鎖的操作,因此在同一操作系統下不同進程可以按照互斥鎖的名稱共用鎖。
正因為如此,互斥鎖的操作會更好資源,性能上相對於臨界區也有降低,在使用時還要多斟酌。對於進程內的線程同步使用臨界區性能會更佳。
在.Net中使用Mutex類來表示互斥量,使用實例的WaitOne()阻止線程執行至到獲取Mutex對象,ReleaseMutex()釋放鎖資源,我們來看一下示例
class MutexTest { //創建Mutex對象 private static Mutex mutex = new Mutex(true, "My"); // static void Main(string[] args) { Run(); Console.ReadLine(); } //模擬多線程調用 public static void Run() { const int count = 2; var threads = new Thread[count]; for (var i = 0; i < count; i++) { var ts = new ThreadStart(UserResource); var t = new Thread(ts); t.Name = "thread" + (i + 1); threads[i] = t; } foreach (var t in threads) { t.Start(); } // Console.WriteLine(string.Format("Creating thread {0} owns the Mutex.", Thread.CurrentThread.Name)); Thread.Sleep(1000); mutex.ReleaseMutex(); Console.WriteLine(string.Format("Creating thread {0} releases the Mutex.", Thread.CurrentThread.Name)); } //修改共用資源值 public static void UserResource() { mutex.WaitOne(); Console.WriteLine(string.Format("Child thread named {0} owns the mutex.", Thread.CurrentThread.Name)); Thread.Sleep(1000); mutex.ReleaseMutex(); Console.WriteLine(string.Format("Child thread named {0} releases the mutex.", Thread.CurrentThread.Name)); } }
Mutex對象是一個全局對象,構造時可以指定name,只要name一樣都認為是同一個Mutext。另外再構造時指定的第一個Bool參數表示創建Mutex對象的線程是否擁有該互斥量。
如果是True表示擁有,必須要釋放後才可以被其它線程使用。上述代碼示例中就需要主線程釋放Mutex。
首先由主線程創建一個Mutex對象,並擁有該Mutex對象
然後主線程接著執行,創建2個線程,線程內部使用WaitOne來阻止該線程繼續執行,直到接收到Mutex對象釋放的信號,方能獲得Mutex使用權,繼續執行。
Sleep 1秒之後,主線程釋放Mutex對象
子線程WaitOne獲得釋放信號並搶占Mutex擁有權,獲得者將進入執行資源代碼,而另外的子現在要等到ReleaseMutex之後才能獲得Mutex擁有權。
在使用Mutex時WaitOne用來阻止線程的執行,直到獲取到Mutex對象的擁有權。也可以指定阻止時間,超時獲取Mutex擁有權失敗,會繼續執行後續代碼,執行完畢無需釋放Mutex。
WaitOne要和ReleaseMutex成對使用,獲取鎖對象後要記得釋放,否則會造成其它線程一直等待狀態。