最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

ReaderWriterLockSlim 在.net framework 3.5的時候就提供了,它是用來代替以前的”fat”版本的”ReaderWriterLock”

這兩個類,有兩種基本的鎖----一個讀鎖,一個寫鎖。

寫鎖是一個完全排他鎖。

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


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

ReaderWriterLockSlim 定義了下面幾個方法來獲取和釋放 讀寫鎖。

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

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

復制代碼 代碼如下:

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

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

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

        static void Read()
        {
            while (true)
            {
                _rw.EnterReadLock();//獲取讀鎖
                //模擬讀的過程
                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(); //獲取寫鎖
                _items.Add(newNumber); //寫數據
                _rw.ExitWriteLock();  //釋放寫鎖
                Console.WriteLine("Thread " + threadID + " added " + newNumber);

                Thread.Sleep(100);
            }
        }

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


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

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

可更新鎖:

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

    獲取一個讀鎖。
    測試,如果要寫的東西在列表中,那么釋放鎖,然后返回。
    釋放讀鎖。
    獲取一個寫鎖
    添加項,寫東西,
    釋放寫鎖。

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

ReaderWriterLockSlim 通過一個叫做可更新鎖( upgradeable lock),來解決這個問題。

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

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

從調用者的角度來看,它很像一個嵌套/遞歸鎖,從功能上講,在第三步,

ReaderWriterLockSlim 在一個原子操作里面釋放讀鎖,然后獲取寫鎖。

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

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

復制代碼 代碼如下:

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

                int newNumber = GetRandomNum(100);

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

                Thread.Sleep(100);
            }
        }


從上面的例子可以看到C#提供的讀寫鎖功能強大,使用方便,

所以在自己編寫讀寫鎖的時候,要考慮下是否需要支持可更新鎖,是否有必要自己寫一個讀寫鎖.

相關文章

  • C#連接mysql的方法【基于vs2010】

    C#連接mysql的方法【基于vs2010】

    這篇文章主要介紹了C#連接mysql的方法,基于vs2010平臺較為詳細的講述了C#操作mysql所需的組件下載、安裝及連接mysql操作實現代碼,需要的朋友可以參考下
    2017-03-03
  • C# 調用Delphi dll 實例代碼

    C# 調用Delphi dll 實例代碼

    這篇文章介紹了C# 調用Delphi dll 實例代碼,有需要的朋友可以參考一下
    2013-09-09
  • 深入淺析C#?11?對?ref?和?struct?的改進

    深入淺析C#?11?對?ref?和?struct?的改進

    這篇文章主要介紹了C#?11?對?ref?和?struct?的改進,有了這些基礎設施,開發(fā)者們將能輕松使用安全的方式來編寫沒有任何堆內存開銷的高性能代碼,需要的朋友可以參考下
    2022-04-04
  • C#基礎知識之FileStream

    C#基礎知識之FileStream

    C#中FileStream對象表示在磁盤或網絡路徑上指向文件的流??梢允褂肍ileStream 類對文件系統(tǒng)上的文件進行讀取、寫入、打開、關閉等。下面我們就來詳細探討下
    2016-07-07
  • C#中使用DevExpress中的ChartControl實現極坐標圖的案例詳解

    C#中使用DevExpress中的ChartControl實現極坐標圖的案例詳解

    這篇文章主要介紹了在C#中使用DevExpress中的ChartControl實現極坐標圖,本案例是使用的是DevExpress 18.1.3版本,之前在14版本上也試過,但是有一個弊端就是實現極坐標圖的時候,第一個點和最后一個點總是自動多一條閉合線,會形成一個閉合的多邊形,因此升級了一下版
    2022-02-02
  • Unity排行榜優(yōu)化滾動效果

    Unity排行榜優(yōu)化滾動效果

    這篇文章主要為大家詳細介紹了Unity排行榜優(yōu)化滾動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Unity3D使用陀螺儀控制節(jié)點旋轉

    Unity3D使用陀螺儀控制節(jié)點旋轉

    這篇文章主要為大家詳細介紹了Unity3D使用陀螺儀控制節(jié)點旋轉,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • C# 在PDF文檔中創(chuàng)建表格的實現方法

    C# 在PDF文檔中創(chuàng)建表格的實現方法

    表格能夠一目了然的讓用戶看到數據信息,使信息顯得有條理化,那么在pdf類型的文檔中如何來添加表格并對表格進行格式化操作呢?下面小編給大家?guī)砹薈# 在PDF文檔中創(chuàng)建表格的實現方法,需要的朋友參考下吧
    2017-12-12
  • C#?中?List?與?List?多層嵌套不改變原值的實現方法(深度復制)

    C#?中?List?與?List?多層嵌套不改變原值的實現方法(深度復制)

    這篇文章主要介紹了C#?中?List?與?List?多層嵌套不改變原值的實現方法,使用?BinaryFormatter?將原始?List?序列化為字節(jié)流,然后再反序列化得到新的?List,實現了深度復制,需要的朋友可以參考下
    2024-03-03
  • C#使用Lambda表達式簡化代碼的示例詳解

    C#使用Lambda表達式簡化代碼的示例詳解

    Lambda,希臘字母λ,在C#編程語言中,被引入為Lambda表達式,表示為匿名函數(匿名方法)。本文將利用Lambda表達式進行代碼的簡化,感興趣的可以了解一下
    2022-12-12

最新評論

泰宁县| 曲沃县| 鹿邑县| 班戈县| 永新县| 鹿邑县| 安康市| 鸡东县| 密山市| 普陀区| 赣榆县| 闽侯县| 鄂伦春自治旗| 迁西县| 临安市| 青田县| 丹阳市| 财经| 循化| 都昌县| 永兴县| 星子县| 桦甸市| 神池县| 元谋县| 云和县| 汉中市| 三亚市| 彭泽县| 同心县| 潮州市| 马边| 宁强县| 江永县| 增城市| 富阳市| 永昌县| 罗田县| 竹北市| 平度市| 凤山县|