熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#多線程學習—生產者和消費者(2)

2022-06-13   來源: .NET編程 

    Monitor 類鎖定一個對象

    當多線程公用一個對象時也會出現和公用代碼類似的問題這種問題就不應該使用lock關鍵字了這裡需要用到SystemThreading中的一個類Monitor我們可以稱之為監視器Monitor提供了使線程共享資源的方案

    Monitor類可以鎖定一個對象一個線程只有得到這把鎖才可以對該對象進行操作對象鎖機制保證了在可能引起混亂的情況下一個時刻只有一個線程可以訪問這個對象

    Monitor必須和一個具體的對象相關聯但是由於它是一個靜態的類所以不能使用它來定義對象而且它的所有方法都是靜態的不能使用對象來引用下面代碼說明了使用Monitor鎖定一個對象的情形

      ……

      Queue oQueue=new Queue()  ……

      MonitorEnter(oQueue)  ……//現在oQueue對象只能被當前線程操縱了  MonitorExit(oQueue)//釋放鎖

    如上所示當一個線程調用MonitorEnter()方法鎖定一個對象時這個對象就歸它所有了其它線程想要訪問這個對象只有等待它使用 MonitorExit()方法釋放鎖為了保證線程最終都能釋放鎖你可以把MonitorExit()方法寫在trycatch finally結構中的finally代碼塊裡

    對於任何一個被Monitor鎖定的對象內存中都保存著與它相關的一些信息其一是現在持有鎖的線程的引用其二是一個預備隊列隊列中保存了已經准備好獲取鎖的線程其三是一個等待隊列隊列中保存著當前正在等待這個對象狀態改變的隊列的引用

    當擁有對象鎖的線程准備釋放鎖時它使用MonitorPulse()方法通知等待隊列中的第一個線程於是該線程被轉移到預備隊列中當對象鎖被釋放時在預備隊列中的線程可以立即獲得對象鎖

    下面是一個展示如何使用lock關鍵字和Monitor類來實現線程的同步和通訊的例子也是一個典型的生產者與消費者問題

    這個例程中生產者線程和消費者線程是交替進行的生產者寫入一個數消費者立即讀取並且顯示(注釋中介紹了該程序的精要所在)

    用到的系統命名空間如下using Systemusing SystemThreading

    首先定義一個被操作的對象的類Cell在這個類裡有兩個方法ReadFromCell()和WriteToCell消費者線程將調用 ReadFromCell()讀取cellContents的內容並且顯示出來生產者進程將調用WriteToCell()方法向 cellContents寫入數據

    示例如下

 public class Cell
{
        int cellContents; // Cell對象裡邊的內容
        bool readerFlag = false; // 狀態標志為true時可以讀取為false則正在寫入
        public int ReadFromCell( )
        {
            lock(this) // Lock關鍵字保證了什麼請大家看前面對lock的介紹
            {
                if (!readerFlag)//如果現在不可讀取
                {
                    try
                    {
                        //等待WriteToCell方法中調用MonitorPulse()方法
                        MonitorWait(this);
                    }
                    catch (SynchronizationLockException e)
                    {
                        ConsoleWriteLine(e);
                    }
                    catch (ThreadInterruptedException e)
                    {
                        ConsoleWriteLine(e);
                    }
                }
                ConsoleWriteLine(Consume: {}cellContents);
                readerFlag = false;
                //重置readerFlag標志表示消費行為已經完成
                MonitorPulse(this);
                //通知WriteToCell()方法(該方法在另外一個線程中執行等待中)
            }
            return cellContents;
        }
   
        public void WriteToCell(int n)
        {
            lock(this)
            {
                if (readerFlag)
                {
                    try
                    {
                        MonitorWait(this);
                    }
                    catch (SynchronizationLockException e)
                    {
                            //當同步方法(指Monitor類除Enter之外的方法)在非同步的代碼區被調用
                        ConsoleWriteLine(e);
                    }
                    catch (ThreadInterruptedException e)
                    {
                            //當線程在等待狀態的時候中止
                        ConsoleWriteLine(e);
                    }
                }
                cellContents = n;
                ConsoleWriteLine(Produce: {}cellContents);
                readerFlag = true;
                MonitorPulse(this);
                //通知另外一個線程中正在等待的ReadFromCell()方法
            }
        }
}
From:http://tw.wingwit.com/Article/program/net/201311/15297.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.