有趣的多线程编程(4)——死锁

80酷酷网    80kuku.com

  编程|多线程

// 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

分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间
点击: