1.lock
Lock锁定一段代码
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock")
违反此准则:
- 如果实例可以被公共访问,将出现 lock (this) 问题。
- 如果 MyType 可以被公共访问,将出现 lock(typeof (MyType)) 问题。
由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。最佳做法是定义 private 对象来锁定, private static 对象变量来保护所有实例所共有的数据。
2.Monitor
Monitor用来锁定一个对象
Monitor具有以下的功能:
- 与某个对象关联。
- 它是未绑定的,可以直接从上下文中引用。
- 不能创建Monitor实例
将为每个同步对象维护以下信息:
- 对当前持有锁的线程的引用。
- 对就绪队列的引用,它包含准备获取锁的线程。
- 对等待队列的引用,它包换正在等待锁定对象状态变化通知的线程。
Code:
1 class MonitorSample 2 { 3 const int MAX_LOOP_TIME = 1000; 4 Queue mQueue; 5 6 public MonitorSample() 7 { 8 mQueue = new Queue(); 9 } 10 public void FirstThread() 11 { 12 int counter = 0; 13 lock (mQueue) 14 { 15 while (counter < MAX_LOOP_TIME) 16 { 17 Monitor.Wait(mQueue); 18 mQueue.Enqueue(counter); 19 Console.WriteLine("Write:{0}", counter); 20 Monitor.Pulse(mQueue); 21 counter++; 22 } 23 } 24 } 25 public void SecondThread() 26 { 27 lock (mQueue) 28 { 29 Monitor.Pulse(mQueue); 30 while (Monitor.Wait(mQueue, 1000)) 31 { 32 int counter = (int)mQueue.Dequeue(); 33 Console.WriteLine("Read:{0}",counter); 34 Monitor.Pulse(mQueue); 35 } 36 } 37 } 38 public int GetQueueCount() 39 { 40 return mQueue.Count; 41 } 42 43 static void Main(string[] args) 44 { 45 MonitorSample test = new MonitorSample(); 46 Thread tFirst = new Thread(new ThreadStart(test.FirstThread)); 47 Thread tSecond = new Thread(new ThreadStart(test.SecondThread)); 48 tFirst.Start(); 49 tSecond.Start(); 50 tFirst.Join(); 51 tSecond.Join(); 52 Console.WriteLine("Queue Count = " + test.GetQueueCount().ToString()); 53 Console.ReadKey(); 54 } 55 }