日期:2014-05-20  浏览次数:21009 次

高手进,分析一个线程同步代码片段优劣
代码实现的功能如下:一个生产者线程,一个消费者程,生产一个产品,消费一个,再生产,再消费...
A版代码如下:
  static void ProduceOneA()
  {
  lock (locker)
  {
  while (true)
  {
  if (isHave)
  Monitor.Wait(locker);

  Thread.Sleep(1000);
  Console.WriteLine("生产一个");
  isHave = true;
  Monitor.Pulse(locker);
  }  
  }
  }

  static void ConsumeOneA()
  {
  lock (locker)
  {
  while (true)
  {
  if(!isHave)
  Monitor.Wait(locker);

  Thread.Sleep(500);
  Console.WriteLine("消费一个");
  isHave = false;
  Monitor.Pulse(locker);
  }
  }
  }

  static object locker = new object();
  volatile static bool isHave = false;

  static void Main(string[] args)
  {
  new Thread(ProduceOneA).Start();
  new Thread(ConsumeOneA).Start();
  }

是比较常见的lock{while(){}}结构,B版代码如下:
  static void ProduceOneB()
  {
  while (true)
  {
  lock (locker)
  {
  if (isHave)
  Monitor.Wait(locker);
  Thread.Sleep(1000);
  Console.WriteLine("生产一个");
  isHave = true;
  Monitor.Pulse(locker);
  }
  }
  }

  static void ConsumeOneB()
  {
  while (true)
  {
  lock (locker)
  {
  if (!isHave)
  Monitor.Wait(locker);
  Thread.Sleep(500);
  Console.WriteLine("消费一个");
  isHave = false;
  Monitor.Pulse(locker);
  }
  }
  }

注意这里变成了while(){lock{}},这两个版本的代码都能达到目的,但孰优孰劣,高手给分析下,个人感觉lock{}里的同步代码应该越短约好如B版代码,但B版的结构频繁调用lock{}又是一个问题...

------解决方案--------------------
C# code

        void ProduceOneA() 
        { 
                while (Interlocked.Read(ref bRun) == 1) 
                { 
                    try
                      {    
                            ProduceHandler.waitone();                
                            Console.WriteLine("生产一个"); 
                            ConsumeHandler.set();
                       }
                      finally
                      {
                          Thread.Sleep(1000);
                      }
                }
        } 

        void ConsumeOneA() 
        { 
                while (Interlocked.Read(ref bRun) == 1) 
                { 
                      try
                      {     ConsumeHandler.waitone();
                            Console.WriteLine("消费一个"); 
                            ProduceHandler.set();
                       }
                      finally
                      {
                          Thread.Sleep(1000);
                      }
                } 
            } 
        } 

        private ReaderWriterLock m_RWHandlers = new ReaderWriterLock();
        long m_Run = 0;
        AutoResetEvent m_ConsumeHandler = new AutoResetEvent(false);
        AutoResetEvent m_ProduceHandler = new AutoResetEvent(true);
        static void Main(string[] args) 
        { 
            Interlocked.Exchange(ref m_Run, 1);
            new Thread(new threadstart(ProduceOneA)).Start(); 
            new Thread(new threadstart(ConsumeOneA)).Start(); 
        }