亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入多線程之:Reader與Write Locks(讀寫(xiě)鎖)的使用詳解

 更新時(shí)間:2013年05月14日 14:40:34   作者:  
本篇文章是對(duì)Reader與Write Locks(讀寫(xiě)鎖)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下

線程安全的一個(gè)很經(jīng)常的需求是允許并發(fā)讀,但是不允許并發(fā)寫(xiě),例如對(duì)于文件就是這樣的。

ReaderWriterLockSlim 在.net framework 3.5的時(shí)候就提供了,它是用來(lái)代替以前的”fat”版本的”ReaderWriterLock”

這兩個(gè)類,有兩種基本的鎖----一個(gè)讀鎖,一個(gè)寫(xiě)鎖。

寫(xiě)鎖是一個(gè)完全排他鎖。

讀鎖可以和其他的讀鎖兼容


因此當(dāng)一個(gè)線程持有寫(xiě)鎖的是很,所有的嘗試獲取讀鎖和寫(xiě)鎖的線程全部阻塞,但是如果沒(méi)有一個(gè)線程持有寫(xiě)鎖,那么可以有一系列的線程并發(fā)的獲取讀鎖。

ReaderWriterLockSlim 定義了下面幾個(gè)方法來(lái)獲取和釋放 讀寫(xiě)鎖。

    Public void EnterReadLock();
    Public void ExitReadLock();
    Public void EnterWriteLock();
    Public void ExitWriteLock();

和Monitor.TryEnter類似,ReaderWriterLockSlim 再對(duì)應(yīng)的”EnterXXX”方法上也提供了相應(yīng)的”Try”版本。ReaderWriterLock提供了AcquireXXX 和 ReleaseXXX 方法,當(dāng)超時(shí)發(fā)生了,ReaderWriterLock 拋出一個(gè)ApplicationException,而不是返回false。

復(fù)制代碼 代碼如下:

static readonly ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
        static List<int> _items = new List<int>();
        static Random _rand = new Random();

        public static void Main()
        {
            ///三個(gè)讀線程
            new Thread(Read).Start();
            new Thread(Read).Start();
            new Thread(Read).Start();

            //兩個(gè)寫(xiě)線程
            new Thread(Write).Start("A");
            new Thread(Write).Start("B");
        }

        static void Read()
        {
            while (true)
            {
                _rw.EnterReadLock();//獲取讀鎖
                //模擬讀的過(guò)程
                foreach (int i in _items)
                    Thread.Sleep(100);
                _rw.ExitReadLock();//釋放讀鎖
            }
        }

        static void Write(object threadID)
        {
            while (true)
            {
                Console.WriteLine(_rw.CurrentReadCount + " concurrent readers");

                int newNumber = GetRandomNum(100);

                _rw.EnterWriteLock(); //獲取寫(xiě)鎖
                _items.Add(newNumber); //寫(xiě)數(shù)據(jù)
                _rw.ExitWriteLock();  //釋放寫(xiě)鎖
                Console.WriteLine("Thread " + threadID + " added " + newNumber);

                Thread.Sleep(100);
            }
        }

        //獲取隨機(jī)數(shù)
        static int GetRandomNum(int max) { lock (_rand) return _rand.Next(max); }


再實(shí)際的發(fā)布版本中,最好使用try/finally 來(lái)確保即使異常拋出了,鎖也被正確的釋放了。

CurrentReadCount 屬性,ReaderWriterLockSlim 提供了以下屬性用來(lái)監(jiān)視鎖。

可更新鎖:

再一個(gè)原子操作里將讀鎖升級(jí)為寫(xiě)鎖是很有用的,例如,假設(shè)你想要再一個(gè)list 里面寫(xiě)一些不存在的項(xiàng)的時(shí)候, 你可能會(huì)執(zhí)行下面的一些步驟:

    獲取一個(gè)讀鎖。
    測(cè)試,如果要寫(xiě)的東西在列表中,那么釋放鎖,然后返回。
    釋放讀鎖。
    獲取一個(gè)寫(xiě)鎖
    添加項(xiàng),寫(xiě)東西,
    釋放寫(xiě)鎖。

問(wèn)題是:在第三步和第四步之間,可能有另一個(gè)線程修改了列表。

ReaderWriterLockSlim 通過(guò)一個(gè)叫做可更新鎖( upgradeable lock),來(lái)解決這個(gè)問(wèn)題。

一個(gè)可更新鎖除了它可以在一個(gè)原子操作中變成寫(xiě)鎖外很像一個(gè)讀鎖,你可以這樣使用它:

    調(diào)用EnterUpgradeableReadLock 獲取可更新鎖。執(zhí)行一些讀操作,例如判斷要寫(xiě)的東西在不在List中。調(diào)用EnterWriteLock , 這個(gè)方法會(huì)將可更新鎖 升級(jí)為 寫(xiě)鎖。執(zhí)行寫(xiě)操作,調(diào)用ExitWriteLock 方法,這個(gè)方法將寫(xiě)鎖轉(zhuǎn)換回可更新鎖。繼續(xù)執(zhí)行一些讀操作,或什么都不做。
    調(diào)用ExitUpgradeableReadLock 釋放可更新鎖。

從調(diào)用者的角度來(lái)看,它很像一個(gè)嵌套/遞歸鎖,從功能上講,在第三步,

ReaderWriterLockSlim 在一個(gè)原子操作里面釋放讀鎖,然后獲取寫(xiě)鎖。

可更新鎖和讀鎖的重要區(qū)別是:盡管可更新鎖可以和讀鎖共存,但是一次只能有一個(gè)可更新鎖被獲取。這樣的主要目的是防止死鎖。

這樣我們可以修改Write方法,讓它可以添加一些不在列表中的Item。

復(fù)制代碼 代碼如下:

static void Write(object threadID)
        {
            while (true)
            {
                Console.WriteLine(_rw.CurrentReadCount + " concurrent readers");

                int newNumber = GetRandomNum(100);

                _rw.EnterUpgradeableReadLock(); //獲取可更新鎖
                if (!_items.Contains(newNumber)) //如果要寫(xiě)的東西不在列表中
                {
                    _rw.EnterWriteLock(); //可更新鎖變成寫(xiě)鎖
                    _items.Add(newNumber); //寫(xiě)東西
                    _rw.ExitWriteLock(); //重新變回可更新鎖
                    Console.WriteLine("Thread " + threadID + " added " + newNumber); //讀數(shù)據(jù)
                }
                _rw.ExitUpgradeableReadLock(); //退出可更新鎖

                Thread.Sleep(100);
            }
        }


從上面的例子可以看到C#提供的讀寫(xiě)鎖功能強(qiáng)大,使用方便,

所以在自己編寫(xiě)讀寫(xiě)鎖的時(shí)候,要考慮下是否需要支持可更新鎖,是否有必要自己寫(xiě)一個(gè)讀寫(xiě)鎖.

相關(guān)文章

最新評(píng)論