溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C# Monitor類的使用

發(fā)布時(shí)間:2020-07-30 18:43:19 來(lái)源:網(wǎng)絡(luò) 閱讀:2085 作者:13713878410 欄目:編程語(yǔ)言

C#中, 通過(guò)System.Threading.Monitor類可以實(shí)現(xiàn)多線程中對(duì)某些代碼塊的同步訪問,以確保數(shù)據(jù)的安全性。


object obj=new object();

Monitor在鎖對(duì)象obj上會(huì)維持兩個(gè)線程隊(duì)列R和W以及一個(gè)引用T :

(1) T是對(duì)當(dāng)前獲得了obj鎖的線程的引用(設(shè)此線程為CurrThread); 

(2) R為就緒隊(duì)列, 其上的線程已經(jīng)準(zhǔn)備好獲取obj鎖。當(dāng)obj鎖被CurrThread釋放后(CurrThread可通過(guò)Monitor.Exit(obj)或 Monitor.Wait(obj)來(lái)釋放其所獲的obj鎖)這些線程就會(huì)去競(jìng)爭(zhēng)obj鎖,獲得obj鎖的線程將被T引用; 線程調(diào)用Monitor.Enter(obj)或Monitor.TryEnter(obj)將會(huì)使該線程直接進(jìn)入R隊(duì)列。

(3) W為等待隊(duì)列,其上的線程是因?yàn)檎{(diào)用了Monitor.Wait(obj)而進(jìn)入W隊(duì)列的;W上的線程不會(huì)被OS直接調(diào)度執(zhí)行,也就是說(shuō)它們沒有準(zhǔn)備好獲取obj鎖,就是說(shuō)在等待隊(duì)列上的線程不能去獲得obj鎖。當(dāng)前獲得obj鎖的線程CurrThread調(diào)用Monitor.Pulse(obj)或Monitor.PulseAll(obj)后會(huì)使W隊(duì)列中的第一個(gè)等待線程或所有等待線程被移至R隊(duì)列,這時(shí)被移至R隊(duì)列的這些線程就有機(jī)會(huì)被OS直接調(diào)度執(zhí)行,也就是有可以去競(jìng)爭(zhēng)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();
        }


輸出結(jié)果:

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();
        }


輸出結(jié)果:

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

因?yàn)門hread2嘗試獲取鎖失敗,所以沒有執(zhí)行鎖內(nèi)部的代碼塊。


例子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);
        }

輸出結(jié)果:

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

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI