C#多線程的用法5-線程間的協作Monitor
阿新 • • 發佈:2017-08-20
ole 所有 pri sum 接下來 變化 customer sta 進入
之前我們使用lock快捷方式,實現了多線程對同一資源的共享。在C#中lock實際上是Monitor操作的簡化版本。
下面使用Monitor來完成之前的lock功能,你可以在此做一下對照:
private static void MultiThreadSynergicWithMonitor() { int[] array = new int[3]; Thread producer = new Thread(() => { int count = 0; Random random = new Random(); while (true) { if (10 == count) break; Monitor.Enter(array); array[0] = random.Next(10); array[1] = random.Next(10); array[2] = random.Next(10); count++; Console.WriteLine(String.Format("{0} work count:{1}。{2}-{3}-{4}", Thread.CurrentThread.Name, count, array[0], array[1], array[2])); Monitor.Exit(array); } }) { Name = "producer" }; Thread customer = new Thread(() => { int count = 0; while (true) { if (10 == count) break; Monitor.Enter(array); count++; Console.WriteLine(String.Format("{0} work count:{1}。{2}-{3}-{4}", Thread.CurrentThread.Name, count, array[0], array[1], array[2])); array[0] = 0; array[1] = 0; array[2] = 0; Monitor.Exit(array); } }) { Name = "customer" }; producer.Start(); customer.Start(); }
通過對比聰明的你可定發現,lock(xx){ }等效於 Monitor.Enter(x‘x)與Monitor.Exit(xx)的組合,實際上lock就是Monitor的語法糖。
因此Monitor比lock在控制線程協作方面更為 強大,如下:
/// <summary> /// 多線程協作-Monitor方式 /// 成功解決多線程對單一資源的共享 /// 並解決多個線程間同步問題 /// </summary> private static void MultiThreadSynergicWithMonitor() { int[] array = new int[3]; Thread producer = new Thread(() => { int count = 0; Random random = new Random(); while (true) { if (10 == count) break; Monitor.Enter(array); array[0] = random.Next(10); array[1] = random.Next(10); array[2] = random.Next(10); count++; Console.WriteLine(String.Format("{0} work count:{1}。{2}-{3}-{4}", Thread.CurrentThread.Name, count, array[0], array[1], array[2])); Monitor.Pulse(array); Monitor.Wait(array); } Monitor.Exit(array); }) { Name = "producer" }; Thread customer = new Thread(() => { int count = 0; while (true) { if (10 == count) break; Monitor.Enter(array); count++; Console.WriteLine(String.Format("{0} work count:{1}。{2}-{3}-{4}", Thread.CurrentThread.Name, count, array[0], array[1], array[2])); array[0] = 0; array[1] = 0; array[2] = 0; Monitor.Pulse(array); Monitor.Wait(array); } Monitor.Exit(array); }) { Name = "customer" }; producer.Start(); customer.Start(); }
上面的代碼與之前的lock代碼功能類似但卻不相同,它實現了producer線程與customer線程的交替運行(與lock方式相比控制更加精細),再次建議你執行一下實際代碼,你會很容易發現兩者卻別。
說明:
1、Monitor.Pulse(xx)實現通知等待xx資源的某一個線程由等待狀態(等待隊列)變更為就緒狀態(就緒隊列),從而做好準備在調用Monitor.Pulse(x‘x)功能的線程釋放資源時馬上鎖定釋放的資源。
2、Monitor.Wait(xx)實現調用該方法的線程暫時釋放鎖定的資源,並讓該線程進入等待線程隊列。所以線程在調用該方法後會臨時中斷後續代碼的執行,在該線程再次獲得資源時,
將回到中斷繼續執行。
3、Monitor.PulseAll(xx)是Monitor.Pulse(xx)擴大版,如果你理解了Monitor.Pulse(xx)並且知道線程狀態的變更(線程所屬隊列的變化),那麽理解Monitor.PulseAll就簡單多了。
Monitor.PulseAll實現將所有等待資源的線程由等待狀態變為就緒狀態,接下來如果資源被釋放,所有就緒線程將均有機會獲得資源並執行。
C#多線程的用法5-線程間的協作Monitor