C# Monitor類的使用

來源:互聯網
上載者:User

標籤:c#   多線程   使用   

C#中, 通過System.Threading.Monitor類可以實現多線程中對某些代碼塊的同步訪問,以確保資料的安全性。


object obj=new object();

Monitor在鎖對象obj上會維持兩個線程隊列R和W以及一個引用T :

(1) T是對當前獲得了obj鎖的線程的引用(設此線程為CurrThread); 

(2) R為就緒隊列,其上的線程已經準備好擷取obj鎖。當obj鎖被CurrThread釋放後(CurrThread可通過Monitor.Exit(obj)或Monitor.Wait(obj)來釋放其所獲的obj鎖)這些線程就會去競爭obj鎖,獲得obj鎖的線程將被T引用; 線程調用Monitor.Enter(obj)或Monitor.TryEnter(obj)將會使該線程直接進入R隊列。

(3) W為等待隊列,其上的線程是因為調用了Monitor.Wait(obj)而進入W隊列的;W上的線程不會被OS直接調度執行,也就是說它們沒有準備好擷取obj鎖,就是說在等待隊列上的線程不能去獲得obj鎖。當前獲得obj鎖的線程CurrThread調用Monitor.Pulse(obj)或Monitor.PulseAll(obj)後會使W隊列中的第一個等待線程或所有等待線程被移至R隊列,這時被移至R隊列的這些線程就有機會被OS直接調度執行,也就是有可以去競爭obj鎖。


Monitor類中的重要方法:

方法名稱
描述
void Enter(object obj) Acquires an exclusive lock on the specified object.
void Enter(object obj, ref bool lockTaken) Acquires an exclusive lock on the specified object, and atomically sets a value that indicates whether the lock was taken.
void Exit(object obj) Releases an exclusive lock on the specified object.
void Pulse(object obj) Notifies a thread in the waiting queue of a change in the locked object‘s state.
void PulseAll(object obj) Notifies all waiting threads of a change in the object‘s state.
bool TryEnter(object obj) Attempts to acquire an exclusive lock on the specified object.
bool TryEnter(object obj, int millisecondsTimeout) Attempts, for the specified number of milliseconds, to acquire an exclusive  lock on the specified object.
bool Wait(object obj) Releases the lock on an object and blocks the current thread until it reacquires
the lock. If the specified time-out interval elapses, the thread enters the ready queue.

例子1:

private object lockObj = new object();        private void Execute()        {            Monitor.Enter(lockObj);            for (int i = 0; i < 5;i++ )            {                Console.WriteLine("Thread Name:" + Thread.CurrentThread.Name + ", Count:" + i);                Thread.Sleep(new Random().Next(5000));            }            Monitor.Exit(lockObj);        }        public void Test()        {            Thread thread1 = new Thread(new ThreadStart(Execute));            thread1.Name = "Thread1";            thread1.Start();            Thread thread2 = new Thread(new ThreadStart(Execute));            thread2.Name = "Thread2";            thread2.Start();                        thread1.Join();            thread2.Join();        }


輸出結果:

Thread Name:Thread1, Count:0
Thread Name:Thread1, Count:1
Thread Name:Thread1, Count:2
Thread Name:Thread1, Count:3
Thread Name:Thread1, Count:4
Thread Name:Thread2, Count:0
Thread Name:Thread2, Count:1
Thread Name:Thread2, Count:2
Thread Name:Thread2, Count:3
Thread Name:Thread2, Count:4


例子2:

         private void Execute1()        {            if (Monitor.TryEnter(lockObj,1000))            {                for (int i = 0; i < 5; i++)                {                    Console.WriteLine("Thread Name:" + Thread.CurrentThread.Name + ", Count:" + i);                    Thread.Sleep(new Random().Next(5000));                }                Monitor.Exit(lockObj);            }        }        public void Test1()        {            Thread thread1 = new Thread(new ThreadStart(Execute1));            thread1.Name = "Thread1";            thread1.Start();            Thread thread2 = new Thread(new ThreadStart(Execute1));            thread2.Name = "Thread2";            thread2.Start();                       thread1.Join();            thread2.Join();        }


輸出結果:

Thread Name:Thread1, Count:0
Thread Name:Thread1, Count:1
Thread Name:Thread1, Count:2
Thread Name:Thread1, Count:3
Thread Name:Thread1, Count:4

因為Thread2嘗試擷取鎖失敗,所以沒有執行鎖內部的代碼塊。


例子3:

        private Queue queue = new Queue();        public void SendThread()        {            int counter = 0;            lock (queue)            {                while (counter < 5)                {                    //Wait, if the queue is busy.                    Monitor.Wait(queue);                    //Push one element.                    queue.Enqueue(counter);                    //Release the waiting thread.                    Monitor.Pulse(queue);                    counter++;                }            }        }        public void ConsumeThread()        {            lock (queue)            {                //Release the waiting thread.                Monitor.Pulse(queue);                //Wait in the loop, while the queue is busy.                //Exit on the time-out when the first thread stops.                while (Monitor.Wait(queue, 1000))                {                    //Pop the first element.                    int counter = (int)queue.Dequeue();                    //Print the first element.                    Console.WriteLine("Queue Value:" + counter.ToString());                    //Release the waiting thread.                    Monitor.Pulse(queue);                }            }        }        public void Test2()        {            Thread thread1 = new Thread(new ThreadStart(SendThread));            thread1.Name = "Thread1";            thread1.Start();            Thread thread2 = new Thread(new ThreadStart(ConsumeThread));            thread2.Name = "Thread2";            thread2.Start();            thread1.Join();            thread2.Join();            Console.WriteLine("Queue Size:" + queue.Count);        }

輸出結果:

Queue Value:0
Queue Value:1
Queue Value:2
Queue Value:3
Queue Value:4
Queue Size:0

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.