1. 程式人生 > >C#多線程的用法5-線程間的協作Monitor

C#多線程的用法5-線程間的協作Monitor

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