C# 多線程系列之Mutex使用


互斥量是一個內核對象,它用來確保一個線程獨占一個資源的訪問,並且互斥量可以用於不同進程中的線程互斥訪問資源。

我們可以把Mutex看作一個出租車,乘客看作線程。乘客首先等車,然后上車,最后下車。當一個乘客在車上時,其他乘客就只有等他下車以后才可以上車。而線程與C# Mutex對象的關系也正是如此,線程使用Mutex.WaitOne()方法等待C# Mutex對象被釋放,如果它等待的C# Mutex對象被釋放了,或者它沒有被任何對象有用,它就自動擁有這個對象,直到它調用Mutex.ReleaseMutex()方法釋放這個對象,而在此期間,其他想要獲取這個C# Mutex對象的線程都只有等待。

Msdn地址:http://msdn.microsoft.com/en-us/library/system.threading.mutex(v=vs.110).aspx

舉MSDN上的例子說明:

using System;
using System.Threading;

class Example
{
    // Create a new Mutex. The creating thread does not own the mutex. 
    private static Mutex mut = new Mutex();
    private const int numIterations = 1;
    private const int numThreads = 3;

    static void Main()
    {
        // Create the threads that will use the protected resource. 
        for(int i = 0; i < numThreads; i++)
        {
            Thread newThread = new Thread(new ThreadStart(ThreadProc));
            newThread.Name = String.Format("Thread{0}", i + 1);
            newThread.Start();
        }

        // The main thread exits, but the application continues to 
        // run until all foreground threads have exited.
    }

    private static void ThreadProc()
    {
        for(int i = 0; i < numIterations; i++)
        {
            UseResource();
        }
    }

    // This method represents a resource that must be synchronized 
    // so that only one thread at a time can enter. 
    private static void UseResource()
    {
        // Wait until it is safe to enter, and do not enter if the request times out.
        Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name);
        if (mut.WaitOne(1000)) {
           Console.WriteLine("{0} has entered the protected area", 
               Thread.CurrentThread.Name);

           // Place code to access non-reentrant resources here. 

           // Simulate some work.
           Thread.Sleep(5000);

           Console.WriteLine("{0} is leaving the protected area", 
               Thread.CurrentThread.Name);

           // Release the Mutex.
              mut.ReleaseMutex();
           Console.WriteLine("{0} has released the mutex", 
                             Thread.CurrentThread.Name);
        }
        else {
           Console.WriteLine("{0} will not acquire the mutex", 
                             Thread.CurrentThread.Name);
        }
    }
}
// The example displays output like the following: 
//       Thread1 is requesting the mutex 
//       Thread1 has entered the protected area 
//       Thread2 is requesting the mutex 
//       Thread3 is requesting the mutex 
//       Thread2 will not acquire the mutex 
//       Thread3 will not acquire the mutex 
//       Thread1 is leaving the protected area 
//       Thread1 has released the mutex

當一個線程占有Mutex后,代碼就可以這樣寫:

 mutex.WaitOne();
 mutex.WaitOne();
 mutex.WaitOne();
 mutex.WaitOne();
。。
。。

WaitOne這個方法被調用時 系統檢查發現mutex沒有被任何線程使用 故而將mutex分配給當前線程
因而就算繼續調用WaitOne也沒有影響 因為系統發現當前線程已經占有 就直接返回了。換言之,waitOne是獲取
Mutex鎖的方式。如果調用ReleaseMutex那么當前線程退出Mutex鎖,其它線程便可進來申請。但是如果調用兩次
ReleaseMutex 那么由於當前線程實際上是不占有鎖的 那么會拋出異常。

所以不能這樣寫:

mutex.ReleaseMutex();//如果已經占有 那么OK
mutex.ReleaseMutex();//調用第二次直接異常

Mutex是一個內核對象,所以,它是可以用作跨進程線程同步的。

A進程可以如此寫:

Mutex mutex = new Mutex(true,"mutex1");

B進程則可以如此寫:

Mutex mutex = Mutex.OpenExisting("mutex1")
OpenExisting這個方法簽名我們后面也可以經常看到,作用就是獲取一個已經存在的內核對象。
獲取到之后的線程同步代碼是跟單進程是一致的。

完畢。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM