您好,登錄后才能下訂單哦!
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
免責(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)容。