// DeadLockSample.cs
// 分析一下为什么会发生死锁?
using System; using System.Threading; public class Test { static readonly object firstLock = new object(); static readonly object secondLock = new object(); static void Main() { new Thread(new ThreadStart(ThreadJob)).Start(); // Wait until we're fairly sure the other thread // has grabbed firstLock Thread.Sleep(500); Console.WriteLine ("Locking secondLock"); lock (secondLock) { Console.WriteLine ("Locked secondLock"); Console.WriteLine ("Locking firstLock"); lock (firstLock) { Console.WriteLine ("Locked firstLock"); } Console.WriteLine ("Released firstLock"); } Console.WriteLine("Released secondLock"); } static void ThreadJob() { Console.WriteLine ("/t/t/t/tLocking firstLock"); lock (firstLock) { Console.WriteLine("/t/t/t/tLocked firstLock"); // Wait until we're fairly sure the first thread // has grabbed secondLock Thread.Sleep(1000); Console.WriteLine("/t/t/t/tLocking secondLock"); lock (secondLock) { Console.WriteLine("/t/t/t/tLocked secondLock"); } Console.WriteLine ("/t/t/t/tReleased secondLock"); } Console.WriteLine("/t/t/t/tReleased firstLock"); } }
Locking firstLock Locked firstLock Locking secondLock Locked secondLock Locking firstLock Locking secondLock |
因应之道,使用Queue和Monitor:
//QueueMonitorThread.cs
using System; using System.Collections; using System.Threading; public class Test { static ProducerConsumer queue; static void Main() { queue = new ProducerConsumer(); new Thread(new ThreadStart(ConsumerJob)).Start(); Random rng = new Random(0); for (int i=0; i < 10; i++) { Console.WriteLine ("Producing {0}", i); queue.Produce(i); Thread.Sleep(rng.Next(1000)); } } static void ConsumerJob() { // Make sure we get a different random seed from the // first thread Random rng = new Random(1); // We happen to know we've only got 10 // items to receive for (int i=0; i < 10; i++) { object o = queue.Consume(); Console.WriteLine ("/t/t/t/tConsuming {0}", o); Thread.Sleep(rng.Next(1000)); } } } public class ProducerConsumer { readonly object listLock = new object(); Queue queue = new Queue(); public void Produce(object o) { lock (listLock) { queue.Enqueue(o); if (queue.Count==1) { Monitor.Pulse(listLock); } } } public object Consume() { lock (listLock) { while (queue.Count==0) { Monitor.Wait(listLock); } return queue.Dequeue(); } } }
Producing 0 Consuming 0 Producing 1 Consuming 1 Producing 2 Consuming 2 Producing 3 Consuming 3 Producing 4 Producing 5 Consuming 4 Producing 6 Consuming 5 Consuming 6 Producing 7 Consuming 7 Producing 8 Consuming 8 Producing 9 Consuming 9 |
Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=589246