C#多线程编程之:Monitor使用示例及Mutex简介
Monitor类功效和lock类似:
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try {
DoSomething();
}finally{
System.Threading.Monitor.Exit(obj);
}
lock关键字比Monitor简洁,其实lock就是对Monitor的Enter和Exit的一个封装。
另外,Monitor还有几个常用的方法:
(1) TryEnter
TryEnter能够有效的决绝长期死等的问题,如果在一个并发经常发生,而且持续时间长的环境中使用TryEnter,可以有效防止死锁或者长时间的等待。
比如我们可以设置一个等待时间:
bool gotLock = Monitor.TryEnter(myobject,1000)
让当前线程在等待1000秒后根据返回的bool值来决定是否继续下面的操作。
(2) Pulse、PulseAll、Wait
Pulse以及PulseAll还有Wait方法是成对使用的,它们能让你更精确的控制线程之间的并发。
示例代码:
1 using System.Threading;
2
3 public class Program
4 {
5 //同步对象
6 static object ball = new object();
7
8 public static void Main()
9 {
10 //创建并启动线程
11 Thread threadPing = new Thread(ThreadPingProc);
12 Thread threadPong = new Thread(ThreadPongProc);
13
14 threadPing.Start();
15 threadPong.Start();
16
17 System.Console.ReadLine();
18 }
19
20 static void ThreadPingProc()
21 {
22 System.Console.WriteLine("Thread Ping Start!");
23
24 //锁定ball
25 lock (ball)
26 {
27 for (int i = 0; i < 5; i++)
28 {
29 System.Console.WriteLine("ThreadPing: Ping ");
30 //通知队列中锁定对象ball的状态更改
31 Monitor.Pulse(ball);
32 //释放ball对象上的锁,并阻止该线程,直到它重新获得ball对象锁
33 Monitor.Wait(ball);
34 }
35
36 //通知队列中锁定对象ball的状态更改
37 Monitor.Pulse(ball);
38 }
39
40 System.Console.WriteLine("ThreadPing: Bye!");
41 }
42
43 static void ThreadPongProc()
44 {
45 System.Console.WriteLine("Thread Pong Start!");
46
47 //锁定ball
48 lock (ball)
49 {
50 for (int i = 0; i < 5; i++)
51 {
52 System.Console.WriteLine("ThreadPong: Pong ");
53 //通知队列中锁定对象ball的状态更改
54 Monitor.Pulse(ball);
55 //释放ball对象上的锁,并阻止该线程,直到它重新获得ball对象锁
56 Monitor.Wait(ball);
57 }
58
59 //通知队列中锁定对象ball的状态更改
60 Monitor.Pulse(ball);
61 }
62
63 System.Console.WriteLine("ThreadPong: Bye!");
64 }
65 }
执行结果如下:
ThreadPing: Hello!
ThreadPing: Ping
ThreadPong: Hello!
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Bye!
ThreadPong: Bye!
当threadPing进程进入ThreadPingProc锁定ball并调用Monitor.Pulse(ball )后,它通知threadPong从阻塞队列进入准备队列。当threadPing调用Monitor.Wait(ball)阻塞自己后,它放弃了了对ball的锁定,所以threadPong得以执行。PulseAll与Pulse方法类似,不过它是向所有在阻塞队列中的进程发送通知信号,如果只有一个线程被阻塞,那么请使用Pulse方法。
Mutex 对象
Mutex与Monitor类似,这里不再累赘。需要注意的是Mutex分两种:一种是本地Mutex,一种是系统级Mutex。系统级Mutex可以用来进行跨进程间的线程的同步。
尽管 Mutex 可以用于进程内的线程同步,但是使用 Monitor 通常更为可取,因为Monitor是专门为 .NET Framework 而设计的,因而它可以更好地利用资源。
相比之下,Mutex 类是 Win32 构造的包装。尽管 Mutex 比Monitor更为强大,但是相对于 Monitor 类,它所需要的互操作转换更消耗计算资源。