a) 使用Mutex类
Mutex是一个特殊的同步类,只能用来同步线程,不过Mutex可以跨进程对线程进行同步。Mutex类确保了一次只有一个线程可以访问同一资源。MSDN中的描述如下:“ Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。”对互斥体,MSDN有如下描述:“互斥体有两种类型:局部互斥体和已命名的系统互斥体。如果使用接受名称的构造函数创建 Mutex 对象,则该对象与具有该名称的操作系统对象关联。已命名的系统互斥体在整个操作系统中都可见,可用于同步进程活动。您可以创建多个 Mutex 对象来表示同一个已命名的系统互斥体,也可以使用 OpenExisting 方法打开现有的已命名系统互斥体。局部互斥体仅存在于您的进程内。您的进程中任何引用局部 Mutex 对象的线程都可以使用它。每个 Mutex 对象都是一个单独的局部互斥体。”
例子4:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class mutex4
{
private static Mutex mut=new Mutex();
private const int numIterations = 1;
private const int numTreads = 3;
static void Main ()
{
Thread myThread = new Thread(new ThreadStart(MyThreadProc));
myThread.Name = "Thread";
Thread myThread1 = new Thread(new ThreadStart(MyThreadProc));
myThread1.Name = "Thread1";
Thread myThread2 = new Thread(new ThreadStart(MyThreadProc));
myThread2.Name = "Thread2";
myThread.Start();
myThread1.Start();
myThread2.Start();
}
private static void MyThreadProc()
{
for (int i = 0; i < numIterations; i++)
{
UseResource();
}
}
private static void UseResource()
{
//mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",Thread.CurrentThread.Name);
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area/r/n",Thread.CurrentThread.Name);
//mut.ReleaseMutex();
}
}
}
这个程序没有加入mut同步机制,运行结果如下:
如果我们把mut.WaitOne()与mut.ReleaseMutex()前的//去掉,运行结果如下:
可以看出,这样线程就完全按我们运行的顺序运行了!
在这里值得一提的是Mutex.WaitOne有三种重载方法:Mutex.WaitOne();Mutex.WaitOne(int [millisecondTimeOut],bool [exitContext]),Mutex.WaitOne(TimeSpan [timeout],bool [exitContext])
其中第一参数是指超时的时间限止,第二个参数指定了线程在重新获取同步上下文之前是否需要先退出同步。
例子5:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class mutexWaitOne5
{
static AutoResetEvent autoEvent = new AutoResetEvent(false); //AutoResetEvent 类表示一个本地等待处理事件,在释放了单个等待线程以后,该事件会在终止时自动重置。而ManualResetEvent在释放了单个等待线程之后只能手动重置
static void Main ()
{
Console.WriteLine(" Main starting.");
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod),autoEvent);//Thread提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。WaitCallback([Method])表示线程池要回调的方法。autoEvent是传入WorkMethod的参数。
if (autoEvent.WaitOne(1000, false))
{
Console.WriteLine("Work method signaled.");
}
else
{
Console.WriteLine("Timed out waiting for work method to signal.");
}
Console.WriteLine("Main ending.");
}
static void WorkMethod(object stateInfo)
{
Console.WriteLine("Work starging.");
int i = new Random().Next(100,2000);
Console.WriteLine("the value of random is {0}",i);
Thread.Sleep(i);
Console.WriteLine("Work ending.");
((AutoResetEvent)stateInfo).Set() ;//将事件状态设为终止态,允许一个或多个等待线程继续
}
}
}
当随机数大于1000时,线程占有互斥体的时间超过了设定值1000,会出现如下结果:
当随机数小于1000时,线程占有互斥体的时间未超过设定值1000,会出现如下结果: