天天看點

C#多線程學習筆記(四) --Lock and Monitor之二

a.Monitor方法(MSDN摘錄)

擷取對象鎖,此操作同樣會标記臨界區的開頭。其他任務線程都不能進入臨界區,除非它使用其他鎖定對象執行臨界區的指令。

Wait

釋放對象上的鎖以便允許其他線程鎖定和通路該對象。在其他線程通路對象時,調用線程将等待。脈沖信号用于通知待待線程有關對象狀态的更改。

Pulse(信号),PulseAll

向一個或多個等待線程發送信号。該信号通知等待線程鎖定對象的狀态已更改,并且鎖的所有者準備釋放該鎖。等待線程被放置在對象的就緒隊列中以便它可以最後接收對象鎖。一旦線程搖籃有了鎖,它就可以檢查對象的新狀态以檢視是否達到所需狀态。

Exit

釋放對象上的鎖。此操作還标記受鎖定對象保護的臨界區的結尾。

b.Sample

C#多線程學習筆記(四) --Lock and Monitor之二

using System;

C#多線程學習筆記(四) --Lock and Monitor之二

using System.Collections.Generic;

C#多線程學習筆記(四) --Lock and Monitor之二

using System.Text;

C#多線程學習筆記(四) --Lock and Monitor之二

using System.Threading;

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

namespace ThreadLockAndMonitor

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

{

C#多線程學習筆記(四) --Lock and Monitor之二

    public class Cell

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

        int cellContents;// Cell對象裡邊的内容

C#多線程學習筆記(四) --Lock and Monitor之二

        bool FAllowReader = false;// 狀态标志,為true時可以讀取,為false則正在寫入

C#多線程學習筆記(四) --Lock and Monitor之二

        public int ReadfromCell()

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            lock (this)// Lock關鍵字保證了該塊隻有一個線程可以進來

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                if (!FAllowReader)//如果現在不可讀取

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                    try

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                        //等待WriteToCell方法中調用Monitor.Pulse()方法

C#多線程學習筆記(四) --Lock and Monitor之二

                        Monitor.Wait(this);

C#多線程學習筆記(四) --Lock and Monitor之二

                    }

C#多線程學習筆記(四) --Lock and Monitor之二

                    catch (SynchronizationLockException e)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                        Console.WriteLine(e.Message);

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                    catch (ThreadInterruptedException e)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                        Console.WriteLine(e);

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                }

C#多線程學習筆記(四) --Lock and Monitor之二

                Console.WriteLine("Consume:{0}", cellContents);

C#多線程學習筆記(四) --Lock and Monitor之二

                FAllowReader = false;//重置FAllowReader标志,表示消費行為已經完成

C#多線程學習筆記(四) --Lock and Monitor之二

                Monitor.Pulse(this);//通知WriteToCell()方法(該方法在另外一個線程中執行,等待中)

C#多線程學習筆記(四) --Lock and Monitor之二

            }

C#多線程學習筆記(四) --Lock and Monitor之二

            return cellContents;

C#多線程學習筆記(四) --Lock and Monitor之二

        }

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

        public void WriteToCell(int _n)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            lock(this)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                if (FAllowReader)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                    catch(SynchronizationLockException e)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                        //當同步方法(指Monitor類除Enter之外的方法)在非同步的代碼區被調用

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                    catch(ThreadInterruptedException e)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                        //當線程在等待狀态的時候中止

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                cellContents = _n;

C#多線程學習筆記(四) --Lock and Monitor之二

                Console.WriteLine("Procduce:{0}", cellContents);

C#多線程學習筆記(四) --Lock and Monitor之二

                FAllowReader = true;

C#多線程學習筆記(四) --Lock and Monitor之二

                Monitor.Pulse(this);//通知另外一個線程中正在等待的ReadFromCell()方法

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

  }

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

    public class CellProd

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

        Cell cell;// 被操作的Cell對象

C#多線程學習筆記(四) --Lock and Monitor之二

        int quantity = 1;//生産者生産次數,初始化為1

C#多線程學習筆記(四) --Lock and Monitor之二

        public CellProd(Cell _box, int _request)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            cell = _box;

C#多線程學習筆記(四) --Lock and Monitor之二

            quantity = _request;

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

        public void ThreadRun()

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            for(int i = 1; i<=quantity; i++)

C#多線程學習筆記(四) --Lock and Monitor之二

                cell.WriteToCell(i);//生産者向操作對象寫入資訊

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

    }

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

    public class CellCons

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

        Cell cell;

C#多線程學習筆記(四) --Lock and Monitor之二

        int quantity = 1;

C#多線程學習筆記(四) --Lock and Monitor之二

        public CellCons(Cell _box, int _request)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            int valReturned;

C#多線程學習筆記(四) --Lock and Monitor之二

            for (int i = 1; i<=quantity; i++)

C#多線程學習筆記(四) --Lock and Monitor之二

                valReturned = cell.ReadfromCell();//消費者從操作對象中讀取資訊

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

    class Program

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

        static void Main(string[] args)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            int result = 0;//一個标志位,如果是0表示程式沒有出錯,如果是1表明有錯誤發生

C#多線程學習筆記(四) --Lock and Monitor之二

            Cell cell = new Cell();

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            //下面使用cell初始化CellProd和CellCons兩個類,生産和消費次數均為20次

C#多線程學習筆記(四) --Lock and Monitor之二

            CellProd prod = new CellProd(cell, 20);

C#多線程學習筆記(四) --Lock and Monitor之二

            CellCons cons = new CellCons(cell, 20);

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            Thread producer = new Thread(new ThreadStart(prod.ThreadRun));

C#多線程學習筆記(四) --Lock and Monitor之二

            Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            //生産者線程和消費者線程都已經被建立,但是沒有開始執行

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            try

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                producer.Start();

C#多線程學習筆記(四) --Lock and Monitor之二

                consumer.Start();

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                producer.Join();

C#多線程學習筆記(四) --Lock and Monitor之二

                consumer.Join();

C#多線程學習筆記(四) --Lock and Monitor之二

                Console.ReadLine();

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            catch(ThreadStateException e)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                Console.WriteLine(e);

C#多線程學習筆記(四) --Lock and Monitor之二

                result = 1;

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            catch(ThreadInterruptedException e)

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

                //當線程在等待狀态的時候中止

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

            //盡管Main()函數沒有傳回值,但下面這條語句可以向父程序傳回執行結果

C#多線程學習筆記(四) --Lock and Monitor之二

            Environment.ExitCode = result;

C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二
C#多線程學習筆記(四) --Lock and Monitor之二

}

C#多線程學習筆記(四) --Lock and Monitor之二

 可以看到,在上面的例程中,同步是通過等待Monitor.Pulse()來完成的。首先生産者生産了一個值,而同一時刻消費者處于等待狀态,直到收到生産者的“脈沖(Pulse)”通知它生産已經完成,此後消費者進入消費狀态,而生産者開始等待消費者完成操作後将調用Monitor.Pulese()發出的“脈沖”。它的執行結果很簡單:

Produce: 1

Consume: 1

Produce: 2

Consume: 2

Produce: 3

Consume: 3

...

Produce: 20

Consume: 20

事實上,這個簡單的例子已經幫助我們解決了多線程應用程式中可能出現的大問題,隻要領悟了解決線程間沖突的基本方法,很容易把它應用到比較複雜的程式中去。