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

C#使用讀寫(xiě)鎖解決多線(xiàn)程并發(fā)問(wèn)題

 更新時(shí)間:2022年04月18日 10:02:55   作者:農(nóng)碼一生  
本文詳細(xì)講解了C#使用讀寫(xiě)鎖解決多線(xiàn)程并發(fā)問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、簡(jiǎn)介

在開(kāi)發(fā)程序的過(guò)程中,難免少不了寫(xiě)入錯(cuò)誤日志這個(gè)關(guān)鍵功能。實(shí)現(xiàn)這個(gè)功能,可以選擇使用第三方日志插件,也可以選擇使用數(shù)據(jù)庫(kù),還可以自己寫(xiě)個(gè)簡(jiǎn)單的方法把錯(cuò)誤信息記錄到日志文件?,F(xiàn)在我們來(lái)講下最后一種方法:

在選擇最后一種方法實(shí)現(xiàn)的時(shí)候,若對(duì)文件操作與線(xiàn)程同步不熟悉,問(wèn)題就有可能出現(xiàn)了,因?yàn)橥粋€(gè)文件并不允許多個(gè)線(xiàn)程同時(shí)寫(xiě)入,否則會(huì)提示“文件正在由另一進(jìn)程使用,因此該進(jìn)程無(wú)法訪問(wèn)此文件”。這是文件的并發(fā)寫(xiě)入問(wèn)題,就需要用到線(xiàn)程同步。而微軟也給線(xiàn)程同步提供了一些相關(guān)的類(lèi)可以達(dá)到這樣的目的,本文使用到的 System.Threading.ReaderWriterLockSlim 便是其中之一。該類(lèi)用于管理資源訪問(wèn)的鎖定狀態(tài),可實(shí)現(xiàn)多線(xiàn)程讀取或進(jìn)行獨(dú)占式寫(xiě)入訪問(wèn)。利用這個(gè)類(lèi),我們就可以避免在同一時(shí)間段內(nèi)多線(xiàn)程同時(shí)寫(xiě)入一個(gè)文件而導(dǎo)致的并發(fā)寫(xiě)入問(wèn)題。讀寫(xiě)鎖是以 ReaderWriterLockSlim 對(duì)象作為鎖管理資源的,不同的 ReaderWriterLockSlim 對(duì)象中鎖定同一個(gè)文件也會(huì)被視為不同的鎖進(jìn)行管理,這種差異可能會(huì)再次導(dǎo)致文件的并發(fā)寫(xiě)入問(wèn)題,所以 ReaderWriterLockSlim 應(yīng)盡量定義為只讀的靜態(tài)對(duì)象。
ReaderWriterLockSlim 有幾個(gè)關(guān)鍵的方法,本文僅討論寫(xiě)入鎖:

1.調(diào)用 EnterWriteLock 方法 進(jìn)入寫(xiě)入狀態(tài),在調(diào)用線(xiàn)程進(jìn)入鎖定狀態(tài)之前一直處于阻塞狀態(tài),因此可能永遠(yuǎn)都不返回。
2.調(diào)用 TryEnterWriteLock 方法 進(jìn)入寫(xiě)入狀態(tài),可指定阻塞的間隔時(shí)間,如果調(diào)用線(xiàn)程在此間隔期間并未進(jìn)入寫(xiě)入模式,將返回false。
3.調(diào)用 ExitWriteLock 方法 退出寫(xiě)入狀態(tài),應(yīng)使用 finally 塊執(zhí)行 ExitWriteLock 方法,從而確保調(diào)用方退出寫(xiě)入模式。

二、不使用讀寫(xiě)鎖寫(xiě)入文件:

代碼:

class Program
    {
        static int LogCount = 100;
        static int WritedCount = 0;
        static int FailedCount = 0;
        static void Main(string[] args)
        {
            //迭代運(yùn)行寫(xiě)入日志記錄,由于多個(gè)線(xiàn)程同時(shí)寫(xiě)入同一個(gè)文件將會(huì)導(dǎo)致錯(cuò)誤
            Parallel.For(0, LogCount, e =>
            {
                WriteLog1();
            });
            Console.WriteLine(string.Format("\r\nLog Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.", LogCount.ToString(), WritedCount.ToString(), FailedCount.ToString()));
            Console.Read();
        }
        #region 未加入讀寫(xiě)鎖
        //不使用讀寫(xiě)鎖寫(xiě)入文件
        static void WriteLog1()
        {
            try
            {
                var logFilePath = "log.txt";
                var now = DateTime.Now;
                var logContent = string.Format("Tid: {0}{1} {2}.{3}\r\n", Thread.CurrentThread.ManagedThreadId.ToString().PadRight(4), now.ToLongDateString(), now.ToLongTimeString(), now.Millisecond.ToString());
                File.AppendAllText(logFilePath, logContent);
                WritedCount++;
            }
            catch (Exception ex)
            {
                FailedCount++;
                Console.WriteLine(ex.Message);
            }
        }
        #endregion
    }

運(yùn)行結(jié)果:

不是所有的log都能寫(xiě)入到log.txt,因?yàn)椴贿m用讀寫(xiě)錯(cuò)可能會(huì)出現(xiàn)上面提到的:“文件正在由另一進(jìn)程使用,因此該進(jìn)程無(wú)法訪問(wèn)此文件”報(bào)錯(cuò)信息。

記錄log信息:

Tid: 9   2021年5月21日 下午 02:18:04.919
Tid: 9   2021年5月21日 下午 02:18:04.944
Tid: 9   2021年5月21日 下午 02:18:05.80
Tid: 11  2021年5月21日 下午 02:18:05.81
Tid: 9   2021年5月21日 下午 02:18:05.82
Tid: 12  2021年5月21日 下午 02:18:05.83
Tid: 11  2021年5月21日 下午 02:18:05.84
Tid: 12  2021年5月21日 下午 02:18:05.84
Tid: 16  2021年5月21日 下午 02:18:05.85
Tid: 12  2021年5月21日 下午 02:18:05.111
Tid: 16  2021年5月21日 下午 02:18:05.117
Tid: 16  2021年5月21日 下午 02:18:05.128
Tid: 11  2021年5月21日 下午 02:18:05.128
Tid: 16  2021年5月21日 下午 02:18:05.133
Tid: 12  2021年5月21日 下午 02:18:05.138
Tid: 16  2021年5月21日 下午 02:18:05.140
Tid: 12  2021年5月21日 下午 02:18:05.140
Tid: 16  2021年5月21日 下午 02:18:05.142
Tid: 16  2021年5月21日 下午 02:18:05.144
Tid: 16  2021年5月21日 下午 02:18:05.151
Tid: 16  2021年5月21日 下午 02:18:05.158
Tid: 9   2021年5月21日 下午 02:18:05.159
Tid: 10  2021年5月21日 下午 02:18:05.159
Tid: 9   2021年5月21日 下午 02:18:05.164
Tid: 16  2021年5月21日 下午 02:18:05.164
Tid: 9   2021年5月21日 下午 02:18:05.172
Tid: 15  2021年5月21日 下午 02:18:05.172
Tid: 16  2021年5月21日 下午 02:18:05.181
Tid: 16  2021年5月21日 下午 02:18:05.187
Tid: 15  2021年5月21日 下午 02:18:05.188
Tid: 16  2021年5月21日 下午 02:18:05.195
Tid: 16  2021年5月21日 下午 02:18:05.196
Tid: 15  2021年5月21日 下午 02:18:05.195
Tid: 16  2021年5月21日 下午 02:18:05.202
Tid: 16  2021年5月21日 下午 02:18:05.203
Tid: 15  2021年5月21日 下午 02:18:05.202
Tid: 15  2021年5月21日 下午 02:18:05.207
Tid: 15  2021年5月21日 下午 02:18:05.209
Tid: 16  2021年5月21日 下午 02:18:05.207
Tid: 15  2021年5月21日 下午 02:18:05.210
Tid: 15  2021年5月21日 下午 02:18:05.222
Tid: 15  2021年5月21日 下午 02:18:05.231
Tid: 18  2021年5月21日 下午 02:18:05.238
Tid: 15  2021年5月21日 下午 02:18:05.238
Tid: 18  2021年5月21日 下午 02:18:05.244
Tid: 15  2021年5月21日 下午 02:18:05.251
Tid: 15  2021年5月21日 下午 02:18:05.256
Tid: 15  2021年5月21日 下午 02:18:05.262
Tid: 15  2021年5月21日 下午 02:18:05.304
Tid: 15  2021年5月21日 下午 02:18:05.312
Tid: 13  2021年5月21日 下午 02:18:05.312
Tid: 9   2021年5月21日 下午 02:18:05.313
Tid: 13  2021年5月21日 下午 02:18:05.320
Tid: 19  2021年5月21日 下午 02:18:05.320
Tid: 16  2021年5月21日 下午 02:18:05.325
Tid: 19  2021年5月21日 下午 02:18:05.333
Tid: 16  2021年5月21日 下午 02:18:05.342
Tid: 16  2021年5月21日 下午 02:18:05.349
Tid: 16  2021年5月21日 下午 02:18:05.361
Tid: 16  2021年5月21日 下午 02:18:05.366
Tid: 16  2021年5月21日 下午 02:18:05.367
Tid: 16  2021年5月21日 下午 02:18:05.368
Tid: 16  2021年5月21日 下午 02:18:05.376
Tid: 16  2021年5月21日 下午 02:18:05.386
Tid: 16  2021年5月21日 下午 02:18:05.392
Tid: 16  2021年5月21日 下午 02:18:05.401
Tid: 9   2021年5月21日 下午 02:18:05.463
Tid: 13  2021年5月21日 下午 02:18:05.464
Tid: 15  2021年5月21日 下午 02:18:05.464
Tid: 13  2021年5月21日 下午 02:18:05.465
Tid: 13  2021年5月21日 下午 02:18:05.470
Tid: 11  2021年5月21日 下午 02:18:05.479

三、使用讀寫(xiě)鎖寫(xiě)入文件:

代碼:

class Program
    {
        static int LogCount = 100;
        static int WritedCount = 0;
        static int FailedCount = 0;
        static void Main(string[] args)
        {
            //迭代運(yùn)行寫(xiě)入日志記錄,由于多個(gè)線(xiàn)程同時(shí)寫(xiě)入同一個(gè)文件將會(huì)導(dǎo)致錯(cuò)誤
            Parallel.For(0, LogCount, e =>
            {
                WriteLog2();
            });
            Console.WriteLine(string.Format("\r\nLog Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.", LogCount.ToString(), WritedCount.ToString(), FailedCount.ToString()));
            Console.Read();
        }
        #region 加入讀寫(xiě)鎖
        //讀寫(xiě)鎖,當(dāng)資源處于寫(xiě)入模式時(shí),其他線(xiàn)程寫(xiě)入需要等待本次寫(xiě)入結(jié)束之后才能繼續(xù)寫(xiě)入
        static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
        static void WriteLog2()
        {
            try
            {
                //設(shè)置讀寫(xiě)鎖為寫(xiě)入模式獨(dú)占資源,其他寫(xiě)入請(qǐng)求需要等待本次寫(xiě)入結(jié)束之后才能繼續(xù)寫(xiě)入
                //注意:長(zhǎng)時(shí)間持有讀線(xiàn)程鎖或?qū)懢€(xiàn)程鎖會(huì)使其他線(xiàn)程發(fā)生饑餓 (starve)。 為了得到最好的性能,需要考慮重新構(gòu)造應(yīng)用程序以將寫(xiě)訪問(wèn)的持續(xù)時(shí)間減少到最小。
                //從性能方面考慮,請(qǐng)求進(jìn)入寫(xiě)入模式應(yīng)該緊跟文件操作之前,在此處進(jìn)入寫(xiě)入模式僅是為了降低代碼復(fù)雜度
                //因進(jìn)入與退出寫(xiě)入模式應(yīng)在同一個(gè)try finally語(yǔ)句塊內(nèi),所以在請(qǐng)求進(jìn)入寫(xiě)入模式之前不能觸發(fā)異常,否則釋放次數(shù)大于請(qǐng)求次數(shù)將會(huì)觸發(fā)異常
                LogWriteLock.EnterWriteLock();
                var logFilePath = "log.txt";
                var now = DateTime.Now;
                var logContent = string.Format("Tid: {0}{1} {2}.{3}\r\n", Thread.CurrentThread.ManagedThreadId.ToString().PadRight(4), now.ToLongDateString(), now.ToLongTimeString(), now.Millisecond.ToString());

                File.AppendAllText(logFilePath, logContent);
                WritedCount++;
            }
            catch (Exception)
            {
                FailedCount++;
            }
            finally
            {
                //退出寫(xiě)入模式,釋放資源占用
                //注意:一次請(qǐng)求對(duì)應(yīng)一次釋放
                //若釋放次數(shù)大于請(qǐng)求次數(shù)將會(huì)觸發(fā)異常[寫(xiě)入鎖定未經(jīng)保持即被釋放]
                //若請(qǐng)求處理完成后未釋放將會(huì)觸發(fā)異常[此模式不下允許以遞歸方式獲取寫(xiě)入鎖定]
                LogWriteLock.ExitWriteLock();
            }
        }
        #endregion
    }

運(yùn)行結(jié)果:

所有的log都完全正確寫(xiě)入到log.txt。

記錄log信息:

Tid: 8   2021年5月21日 下午 02:26:36.573
Tid: 8   2021年5月21日 下午 02:26:36.597
Tid: 8   2021年5月21日 下午 02:26:36.599
Tid: 8   2021年5月21日 下午 02:26:36.600
Tid: 8   2021年5月21日 下午 02:26:36.601
Tid: 8   2021年5月21日 下午 02:26:36.602
Tid: 8   2021年5月21日 下午 02:26:36.608
Tid: 8   2021年5月21日 下午 02:26:36.609
Tid: 8   2021年5月21日 下午 02:26:36.614
Tid: 8   2021年5月21日 下午 02:26:36.616
Tid: 8   2021年5月21日 下午 02:26:36.617
Tid: 8   2021年5月21日 下午 02:26:36.620
Tid: 8   2021年5月21日 下午 02:26:36.620
Tid: 8   2021年5月21日 下午 02:26:36.621
Tid: 8   2021年5月21日 下午 02:26:36.622
Tid: 8   2021年5月21日 下午 02:26:36.623
Tid: 8   2021年5月21日 下午 02:26:36.624
Tid: 8   2021年5月21日 下午 02:26:36.624
Tid: 8   2021年5月21日 下午 02:26:36.625
Tid: 8   2021年5月21日 下午 02:26:36.626
Tid: 8   2021年5月21日 下午 02:26:36.626
Tid: 8   2021年5月21日 下午 02:26:36.627
Tid: 8   2021年5月21日 下午 02:26:36.628
Tid: 8   2021年5月21日 下午 02:26:36.628
Tid: 8   2021年5月21日 下午 02:26:36.629
Tid: 8   2021年5月21日 下午 02:26:36.630
Tid: 8   2021年5月21日 下午 02:26:36.630
Tid: 8   2021年5月21日 下午 02:26:36.631
Tid: 8   2021年5月21日 下午 02:26:36.632
Tid: 8   2021年5月21日 下午 02:26:36.632
Tid: 8   2021年5月21日 下午 02:26:36.633
Tid: 8   2021年5月21日 下午 02:26:36.634
Tid: 8   2021年5月21日 下午 02:26:36.634
Tid: 8   2021年5月21日 下午 02:26:36.635
Tid: 8   2021年5月21日 下午 02:26:36.636
Tid: 8   2021年5月21日 下午 02:26:36.636
Tid: 8   2021年5月21日 下午 02:26:36.637
Tid: 8   2021年5月21日 下午 02:26:36.638
Tid: 8   2021年5月21日 下午 02:26:36.638
Tid: 8   2021年5月21日 下午 02:26:36.639
Tid: 8   2021年5月21日 下午 02:26:36.641
Tid: 8   2021年5月21日 下午 02:26:36.641
Tid: 8   2021年5月21日 下午 02:26:36.642
Tid: 8   2021年5月21日 下午 02:26:36.643
Tid: 8   2021年5月21日 下午 02:26:36.644
Tid: 8   2021年5月21日 下午 02:26:36.644
Tid: 8   2021年5月21日 下午 02:26:36.645
Tid: 8   2021年5月21日 下午 02:26:36.646
Tid: 8   2021年5月21日 下午 02:26:36.647
Tid: 8   2021年5月21日 下午 02:26:36.647
Tid: 8   2021年5月21日 下午 02:26:36.648
Tid: 8   2021年5月21日 下午 02:26:36.649
Tid: 8   2021年5月21日 下午 02:26:36.650
Tid: 8   2021年5月21日 下午 02:26:36.650
Tid: 8   2021年5月21日 下午 02:26:36.651
Tid: 8   2021年5月21日 下午 02:26:36.652
Tid: 8   2021年5月21日 下午 02:26:36.652
Tid: 8   2021年5月21日 下午 02:26:36.652
Tid: 8   2021年5月21日 下午 02:26:36.653
Tid: 8   2021年5月21日 下午 02:26:36.654
Tid: 8   2021年5月21日 下午 02:26:36.655
Tid: 8   2021年5月21日 下午 02:26:36.656
Tid: 8   2021年5月21日 下午 02:26:36.658
Tid: 8   2021年5月21日 下午 02:26:36.658
Tid: 8   2021年5月21日 下午 02:26:36.659
Tid: 8   2021年5月21日 下午 02:26:36.660
Tid: 8   2021年5月21日 下午 02:26:36.660
Tid: 8   2021年5月21日 下午 02:26:36.661
Tid: 8   2021年5月21日 下午 02:26:36.662
Tid: 8   2021年5月21日 下午 02:26:36.662
Tid: 8   2021年5月21日 下午 02:26:36.663
Tid: 8   2021年5月21日 下午 02:26:36.664
Tid: 8   2021年5月21日 下午 02:26:36.664
Tid: 8   2021年5月21日 下午 02:26:36.665
Tid: 8   2021年5月21日 下午 02:26:36.666
Tid: 8   2021年5月21日 下午 02:26:36.666
Tid: 8   2021年5月21日 下午 02:26:36.667
Tid: 8   2021年5月21日 下午 02:26:36.668
Tid: 8   2021年5月21日 下午 02:26:36.669
Tid: 8   2021年5月21日 下午 02:26:36.669
Tid: 8   2021年5月21日 下午 02:26:36.670
Tid: 8   2021年5月21日 下午 02:26:36.671
Tid: 8   2021年5月21日 下午 02:26:36.672
Tid: 8   2021年5月21日 下午 02:26:36.673
Tid: 8   2021年5月21日 下午 02:26:36.675
Tid: 8   2021年5月21日 下午 02:26:36.675
Tid: 8   2021年5月21日 下午 02:26:36.676
Tid: 8   2021年5月21日 下午 02:26:36.677
Tid: 14  2021年5月21日 下午 02:26:36.678
Tid: 15  2021年5月21日 下午 02:26:36.679
Tid: 16  2021年5月21日 下午 02:26:36.680
Tid: 17  2021年5月21日 下午 02:26:36.681
Tid: 18  2021年5月21日 下午 02:26:36.681
Tid: 20  2021年5月21日 下午 02:26:36.683
Tid: 9   2021年5月21日 下午 02:26:36.683
Tid: 19  2021年5月21日 下午 02:26:36.684
Tid: 10  2021年5月21日 下午 02:26:36.685
Tid: 11  2021年5月21日 下午 02:26:36.685
Tid: 12  2021年5月21日 下午 02:26:36.687
Tid: 13  2021年5月21日 下午 02:26:36.688

到此這篇關(guān)于C#使用讀寫(xiě)鎖解決多線(xiàn)程并發(fā)問(wèn)題的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

库尔勒市| 高淳县| 黔西| 安平县| 丹巴县| 涡阳县| 仁怀市| 黎川县| 石渠县| 富平县| 白银市| 湘乡市| 郧西县| 分宜县| 白城市| 乐清市| 临沂市| 逊克县| 涡阳县| 永清县| 武邑县| 泸西县| 兴宁市| 靖安县| 安徽省| 香河县| 垫江县| 林州市| 赞皇县| 遵义县| 河曲县| 桃园市| 册亨县| 永城市| 汽车| 勐海县| 五大连池市| 玛曲县| 汽车| 万年县| 内江市|