C# 線程同步之排它鎖/Monitor監視器類


一、Monitor類說明,提供同步訪問對象的機制。

1.位於System.Threading命名空間下,mscorlib.dll程序集中。

2.Monitor通過獲取和釋放排它鎖的方式實現多線程的同步問題。

3.Monitor實現當前進程內的多線程的同步,和lock語句的功能類似。

4.當前為靜態類,使用簡單

5.依賴的鎖定對象和lock語句中類似,同樣需要引用類型、建議私有、只讀、靜態

定義代碼:

    //
    // 摘要:
    //     提供同步訪問對象的機制。
    [ComVisible(true)]
    public static class Monitor

二、常用方法說明

1.Enter(obj)方法 在指定對象上獲取排它鎖。

2.Exit(obj)   釋放指定對象上的排他鎖。

3.IsEntered(obj) 判斷當前線程是否已經持有排它鎖

4.TryEnter(object obj, TimeSpan timeout)  在指定的時間量內嘗試獲取指定對象上的排他鎖。

5.Wait(object obj) 釋放對象上的鎖並阻止當前線程,直到它重新獲取該鎖。

6.Pulse(object obj) 通知等待隊列中的線程鎖定對象狀態的更改。

7.PulseAll(object obj)  通知所有的等待線程對象狀態的更改。

三、示例說明一:

說明:多線程累加數值,解決同步問題

private readonly static object _MyLock = new object();
static int Count = 0;
static void CountAdd()
{
    Monitor.Enter(_MyLock); //獲取排它鎖
    Count++;
    Console.WriteLine(Count);
    if (Count == 10)
    {
        Count = 0;
    }
    Monitor.Exit(_MyLock); //釋放排它鎖
}
public static void TestOne()
{
    //啟動4個線程,累加Count
    for (int i = 0; i < 4; i++)
    {
        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                CountAdd();
                Thread.Sleep(500 * i);
            }
        });
    }
}

1.如果不使用排它鎖處理,會出現數據異常

2.使用鎖定結果會正常

四、借助於using(){} 塊實現鎖定處理

1.此場景在事務處理中可能會用到,保證同一個事務,如果一個線程開啟操作,其他線程對當前事務操作等待。

2.此場景對於外部使用,不需要考慮多線程問題

1.繼承了IDisposable接口的封裝

    class AddHelper : IDisposable
    {

        private readonly static object _MyLock = new object();
        static int Count = 0;
        public AddHelper()
        {
            //啟用排它鎖
            Monitor.Enter(_MyLock);
        }
        public void AddCount()
        {
            Count++;
            Console.WriteLine(Count);
            if (Count == 10)
            {
                Count = 0;
            }
        }
        public void Dispose()
        {
            //釋放排它鎖
            Monitor.Exit(_MyLock);
        }
    }

2.調用代碼塊

public static void TestTwo()
{
    //啟動4個線程,累加Count
    for (int i = 0; i < 4; i++)
    {
        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                //如果不使用排他鎖處理,會出現數據異常
                //AddHelper _add = new AddHelper();
                //_add.AddCount();

                //將排他鎖處理封裝
                using (AddHelper _add = new AddHelper())
                {
                    _add.AddCount();
                }
                Thread.Sleep(500 * i);
            }
        });
    }
}

更多參考:

C# lock關鍵詞/lock語句塊、線程鎖

 C# using 關鍵字使用整理

 EntiryFramework中事務操作(二)

官方參考:https://msdn.microsoft.com/zh-cn/library/system.threading.monitor.aspx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM