Mutex就像一个C#锁(lock),但它可以跨多个进程工作。换句话说,Mutex可以是计算机范围的,也可以是应用程序范围的。
Mutex是一个同步原语,也可用于进程间同步。当两个或多个线程需要同时访问共享资源时,系统需要一个同步机制来确保一次只有一个线程使用该资源。Mutex是一个同步原语,它只允许对一个线程的共享资源进行独占访问。如果一个线程获得了一个Mutex,那么想要获取该Mutex的第二个线程将被挂起,直到第一个线程释放Mutex。
简而言之,互斥(“Mutex”)是一种机制,它充当一个标志,以防止两个线程同时执行一个或多个操作。您想要独占运行的整个操作称为关键部分或受保护部分。
关键部分是访问共享资源(数据结构或设备)的一段代码,但条件是一次只能有一个线程进入此部分。
现代编程语言天生就支持这一点。。在C#中,像下面这样简单:
实例化可从每个线程访问的新静态Mutex对象。
在每个线程中使用该对象的WaitOne()和ReleaseMutex()方法包装您想要在关键部分执行的任何代码
使用Mutex类,您可以调用WaitHandle.WaitOne方法加锁,用ReleaseMutex释放这个锁。关闭或dispose Mutex会自动释放它。与lock语句一样,Mutex只能从获取它的同一个线程中释放。
以下示例显示如何使用本地Mutex对象来同步对受保护资源的访问。
using System;
using System.Collections;
using System.Threading;
namespace Mutexclass
{
class Akshay { private static Mutex mutex = new Mutex(); private const int numhits = 1; private const int numThreads = 4; private static void ThreadProcess() { for (int i = 0; i < numhits; i++) { UseCsharpcorner(); } } private static void UseCsharpcorner() { mutex.WaitOne(); // Wait until it is safe to enter. Console.WriteLine("{0} has entered in the C_sharpcorner.com", Thread.CurrentThread.Name); // Place code to access non-reentrant resources here. Thread.Sleep(500); // Wait until it is safe to enter. Console.WriteLine("{0} is leaving the C_sharpcorner.com\r\n", Thread.CurrentThread.Name); mutex.ReleaseMutex(); // Release the Mutex. } static void Main(string[] args) { for (int i = 0; i < numThreads; i++) { Thread mycorner = new Thread(new ThreadStart(ThreadProcess)); mycorner.Name = String.Format("Thread{0}", i + 1); mycorner.Start(); } Console.Read(); } }
}
用Mutex来控制针对两个当前线程的共享资源
using System;
using System.Threading;
class MyCounter
{ public static int count = 0; public static Mutex MuTexLock = new Mutex();
}
class IncThread
{ public Thread th; public IncThread() { th = new Thread(this.GO); th.Start(); } void Go() { Console.WriteLine("IncThread is waiting for the mutex."); MyCounter.MuTexLock.WaitOne(); Console.WriteLine("IncThread acquires the mutex."); int num = 10; do { Thread.Sleep(50); MyCounter.count++; Console.WriteLine("In IncThread, MyCounter.count is " + MyCounter.count); num--; } while (num > 0); Console.WriteLine("IncThread releases the mutex."); MyCounter.MuTexLock.ReleaseMutex(); }
}
class DecThread
{ public Thread th; public DecThread() { th = new Thread(new ThreadStart(this.Go)); th.Start(); }| void Go()
| { Console.WriteLine("DecThread is waiting for the mutex."); MyCounter.MuTexLock.WaitOne(); Console.WriteLine("DecThread acquires the mutex."); int num = 10; do { Thread.Sleep(50); MyCounter.count--; Console.WriteLine("In DecThread, MyCounter.count is " + MyCounter.count); num--; } while (num > 0); Console.WriteLine("DecThread releases the mutex."); MyCounter.MuTexLock.ReleaseMutex(); }
}
class MainClass
{ public static void Main() {| IncThread myt1 = new IncThread(); DecThread myt2 = new DecThread(); myt1.thrd.Join(); myt2.thrd.Join(); Console.Read(); }
}
使用Mutex对象:WaitOne
重载的WaitOne()方法也接受TimeSpan对象,如果线程需要等待一段时间后执行的场景很有用。通常,当存在当两个或多个线程正在等待同一个互斥锁同时可用导致死锁的风险时使用此方法,。死锁听起来很糟糕,因为它可能导致应用程序互相等待导致而出现无响应或者超时。
using System;
using System.Threading;
namespace waitonmethod
{
class Akshay { private static int Runs = 0; static Mutex mutex = new Mutex(false, "RunsMutex");| public static void CountUp() { while (Runs < 10) { // acquire the mutex mutex.WaitOne(); int Temp = Runs; Temp++; Console.WriteLine(Thread.CurrentThread.Name + " " + Temp); Thread.Sleep(800); Runs = Temp; // release the mutex mutex.ReleaseMutex(); } } public static void Main() { Thread t2 = new Thread(new ThreadStart(CountUp)); t2.Name = "t2"; Thread t3 = new Thread(new ThreadStart(CountUp)); t3.Name = "t3"; t2.Start(); t3.Start(); Console.Read(); } }
}
得到互斥锁
互斥对象由线程拥有。当拥有时,它只能由一个线程拥有。当它由一个线程拥有时,在原始线程所有者释放它之前,其他线程不能拥有它。想要拥有互斥对象的线程调用互斥对象实例的WaitOne()方法。想要释放互斥锁的拥有线程调用ReleaseMutex()方法。
using System;
using System.Threading;
namespace ownamutex
{ class Akshay { public static void Main() { bool ownsMutex; using (Mutex mutex = new Mutex(true, "MutexExample", out ownsMutex)) { if (ownsMutex) { Console.WriteLine("Owned"); mutex.ReleaseMutex(); } else { Console.WriteLine("Another instance of this application " +" already owns the mutex named MutexExample."); } } Console.Read(); } }
}
命名Mutex
Mutex可以取别名,也可以默认。如果对互斥锁命名,那么它就有资格成为可以从多个进程访问的系统级别的互斥锁。如果互斥锁未命名,则它是一个匿名互斥锁,只能在创建互斥锁的进程内访问。
using System;
using System.Threading;
namespace Namingthread
{ class Akshay { public static void Main(string[] args) { string mutexName = "akshay"; Mutex m = new Mutex(false, mutexName); for (; ; ) { m.WaitOne(); Console.WriteLine("Have Mutex"); Console.WriteLine("Releasing"); m.ReleaseMutex(); } Console.Read(); } }
}
https://www.c-sharpcorner.com/UploadFile/1d42da/threading-with-mutex/
Akshay Teotia C# Corner
https://pdfs.semanticscholar.org/326a/0e09be808978c3bb9fdd006f3041dc0cbc13.pdf
Runtime Code Generation with JVM and CLR