C# 線程同步之Monitor

來源:互聯網
上載者:User

本文用經典的生產者消費者的例子,說明Mnitor對象的用法。實現的目標是:

生產者生產一個資料,然後消費者開始消費,消費完成後生產者繼續生產,迴圈10次後結束。

下面是代碼:

    namespace ConsoleTest
   {
    /// <summary>
    /// 生產者消費者例子
    /// </summary>
   public class Producer_Consumer
    {
       /// <summary>
       /// 生產者生產資料
       /// </summary>
       private void produce()
       {
           for (int i = 0; i < 10;i++ )
           {
               try
               {
                   Monitor.Enter(_locker); //在調用Wait方法前必須擷取對象的鎖
                   {
                       Monitor.Wait(_locker); //阻塞當前線程,釋放鎖,進入等待狀態
                       Thread.Sleep(500); //此處是為了讓程式的執行過程更清楚
                       _count++;
                       Console.WriteLine("生產者: " + _count);
                       Monitor.Pulse(_locker); //通知等待擷取鎖(即調用Wait方法的線程)的消費者線程進入就緒狀態
                   }
               }
               finally
               {
                   Monitor.Exit(_locker); //釋放鎖
               }

           }

       }

       /// <summary>
       /// 消費者消費資料
       /// </summary>
       private void consume()
       {
           try
           {
               Monitor.Enter(_locker); //在調用Pulse方法前必須擷取對象的鎖
               {
                   Monitor.Pulse(_locker); //此處不加這句代碼會造成死結
                   while (Monitor.Wait(_locker)) //迴圈等待生產者線程生產資料完成
                   {
                       Thread.Sleep(500);
                       Console.WriteLine("消費者:" + _count);
                       Monitor.Pulse(_locker); //消費完成後,通知生產者繼續生產
                       if (_count == 10)
                       {
                           Console.ReadLine();
                           return; //消費完10個資料後程式退出
                       }
                   }
               }
           }
           finally
           {
               Monitor.Exit(_locker);//釋放鎖
           }
       }

       public void Test()
       {
           Thread thread1 = new Thread(produce);
           Thread thread2 = new Thread(consume);

           thread1.Start();
           thread2.Start();
       }

       private int _count;
       private object _locker = new object();
       }
    }

    代碼中有幾個地方需要注意:

    1、Monitor.Enter(object)方法是擷取鎖,Monitor.Exit(object)方法是釋放鎖,為了避免在擷取鎖後發

         生異常,導致鎖無法釋放,所以要在finally塊中釋放鎖。經常用的lock(object){}其實是用如下方式實現的:

     try{

         Monitor.Enter(object);

        //do something

         }

      finally{

        Monitor.Exit(object);

      }

    2、Monitor.Pluse(object)調用後,程式不會立即轉向Minitor.Wait(object)執行,

它只是讓Wait的線程進入就緒狀態,獲得執行的可能性。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.