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

C#多線(xiàn)程編程中的鎖系統(tǒng)(二)

 更新時(shí)間:2015年04月10日 09:37:39   投稿:junjie  
這篇文章主要介紹了C#多線(xiàn)程編程中的鎖系統(tǒng)(二),本文講解了volatile、Interlocked、ReaderWriterLockSlim等升級(jí)鎖和原子操作的使用實(shí)例,需要的朋友可以參考下

上章主要講排他鎖的直接使用方式。但實(shí)際當(dāng)中全部都用鎖又太浪費(fèi)了,或者排他鎖粒度太大了。 這一次我們說(shuō)說(shuō)升級(jí)鎖和原子操作。

目錄
1:volatile
2:  Interlocked
3:ReaderWriterLockSlim
4:總結(jié)

一:volatile

簡(jiǎn)單來(lái)說(shuō): volatile關(guān)鍵字是告訴c#編譯器和JIT編譯器,不對(duì)volatile標(biāo)記的字段做任何的緩存。確保字段讀寫(xiě)都是原子操作,最新值。

這不就是鎖嗎?   其這貨它根本不是鎖, 它的原子操作是基于CPU本身的,非阻塞的。 因?yàn)?2位CPU執(zhí)行賦值指令,數(shù)據(jù)傳輸最大寬度4個(gè)字節(jié)。

所以只要在4個(gè)字節(jié)以下讀寫(xiě)操作的,32位CPU都是原子操作。volatile 它就是利用這個(gè)特性來(lái)的。

好殘酷的事實(shí)?不然,微軟大法這樣是為了提高JIT性能效率,對(duì)有些數(shù)據(jù)進(jìn)行緩存了(多線(xiàn)程下)。

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

  //正確
       public volatile Int32 score1 = 1;
        //報(bào)錯(cuò)
        public volatile Int64 score2 = 1;

看上面的例子,我們定義8個(gè)字節(jié)長(zhǎng)度score2就不行了。  因?yàn)?個(gè)字節(jié),32位CPU就分成2個(gè)指令執(zhí)行了。自然就無(wú)法保證原子操作了。

這么細(xì)節(jié)的,忘了怎么辦,那豈不是坑人啊。  于是微軟大法直接一棍子打死,限制4個(gè)字節(jié)以下的類(lèi)型字段才能用volatile,具體什么、看msdn吧。

那今天我知道了。我編譯平臺(tái)改成64位上,只在64位CPU用volatile  int64,行不行?  不行,編譯器報(bào)錯(cuò)。說(shuō)了一棍子打死了。。

(^._.^)ノ  好吧,其實(shí)可以用IntPtr這個(gè)。

 volatile多數(shù)情況下很有用處的,畢竟鎖的性能開(kāi)銷(xiāo)還是很大的。我們可以把當(dāng)成輕量級(jí)的鎖,根據(jù)具體場(chǎng)景合理使用,能提高不少程序性能。

線(xiàn)程中的Thread.VolatileRead 和Thread.VolatileWrite 就是volatile的復(fù)雜版。

二:Interlocked

MSDN 描述:為多個(gè)線(xiàn)程共享的變量提供原子操作。主要函數(shù)如下:

Interlocked.Increment    原子操作,遞增指定變量的值并存儲(chǔ)結(jié)果。
Interlocked.Decrement       原子操作,遞減指定變量的值并存儲(chǔ)結(jié)果。
Interlocked.Add        原子操作,添加兩個(gè)整數(shù)并用兩者的和替換第一個(gè)整數(shù)

Interlocked.CompareExchange(ref a, b, c);  原子操作,a參數(shù)和c參數(shù)比較,  相等b替換a,不相等不替換。

基本用法就不多說(shuō)了。直接來(lái)段CLR via C# interlock anything的例子:

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

public static int Maximum(ref int target, int value)
        {
            int currentVal = target, startVal, desiredVal;  //記錄前后值
            do
            {
                startVal = currentVal; //記錄循環(huán)迭代的初始值。
                desiredVal = Math.Max(startVal, value); //基于startVal和value計(jì)算期望值desiredVal

                //高并發(fā)下,線(xiàn)程被搶占情況下,target值會(huì)發(fā)生改變。

                //target startVal相等說(shuō)明沒(méi)改變。desiredVal 直接替換。
                currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal);

            } while (startVal != currentVal); //不相等說(shuō)明,target值已經(jīng)被其他線(xiàn)程改動(dòng)。自旋繼續(xù)。
            return desiredVal;
        }

三:ReaderWriterLockSlim

假如我們有份緩存數(shù)據(jù)A,如果每次都不管任何操作lock一下,那么我的這份緩存A就永遠(yuǎn)只能單線(xiàn)程讀寫(xiě)了, 這在Web高并發(fā)下是不能忍受的。

那有沒(méi)有一種辦法我只在寫(xiě)入時(shí)進(jìn)入獨(dú)占鎖呢,讀操作時(shí)不限制線(xiàn)程數(shù)量呢?答案就是我們的ReaderWriterLockSlim主角,讀寫(xiě)鎖。

ReaderWriterLockSlim 其中一種鎖EnterUpgradeableReadLock最關(guān)鍵  即可升級(jí)鎖。 

它呢允許你先進(jìn)入讀鎖,發(fā)現(xiàn)緩存A不一樣了, 再進(jìn)入寫(xiě)鎖,寫(xiě)入后退回讀鎖模式。

ps: 這里注意下net 3.5之前有個(gè)ReaderWriterLock 性能較差。推薦使用升級(jí)版的 ReaderWriterLockSlim 。

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

//實(shí)例一個(gè)讀寫(xiě)鎖
 ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);

上面實(shí)例一個(gè)讀寫(xiě)鎖,這里注意的是構(gòu)造函數(shù)的枚舉。

LockRecursionPolicy.NoRecursion 不支持,發(fā)現(xiàn)遞歸會(huì)拋異常。

LockRecursionPolicy.SupportsRecursion  即支持遞歸模式,線(xiàn)程鎖中繼續(xù)在使用鎖。

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

cacheLock.EnterReadLock();
            //do
                cacheLock.EnterReadLock();
                //do
                cacheLock.ExitReadLock();
            cacheLock.ExitReadLock();

這種模式極易容易死鎖,比如讀鎖里面使用寫(xiě)鎖。

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

cacheLock.EnterReadLock();
            //do
              cacheLock.EnterWriteLock();
              //do
              cacheLock.ExitWriteLock();
            cacheLock.ExitReadLock();

下面是直接拿msdn的緩存例子了,加了簡(jiǎn)單注釋。

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

public class SynchronizedCache
    {
        private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
        private Dictionary<int, string> innerCache = new Dictionary<int, string>();

        public string Read(int key)
        {
            //進(jìn)入讀鎖,允許其他所有的讀線(xiàn)程,寫(xiě)入線(xiàn)程被阻塞。
            cacheLock.EnterReadLock();
            try
            {
                return innerCache[key];
            }
            finally
            {
                cacheLock.ExitReadLock();
            }
        }

        public void Add(int key, string value)
        {
            //進(jìn)入寫(xiě)鎖,其他所有訪(fǎng)問(wèn)操作的線(xiàn)程都被阻塞。即寫(xiě)?yīng)氄兼i。
            cacheLock.EnterWriteLock();
            try
            {
                innerCache.Add(key, value);
            }
            finally
            {
                cacheLock.ExitWriteLock();
            }
        }

        public bool AddWithTimeout(int key, string value, int timeout)
        {
            //超時(shí)設(shè)置,如果在超時(shí)時(shí)間內(nèi),其他寫(xiě)鎖還不釋放,就放棄操作。
            if (cacheLock.TryEnterWriteLock(timeout))
            {
                try
                {
                    innerCache.Add(key, value);
                }
                finally
                {
                    cacheLock.ExitWriteLock();
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        public AddOrUpdateStatus AddOrUpdate(int key, string value)
        {
            //進(jìn)入升級(jí)鎖。 同時(shí)只能有一個(gè)可升級(jí)鎖線(xiàn)程。寫(xiě)鎖,升級(jí)鎖都被阻塞,但允許其他讀取數(shù)據(jù)的線(xiàn)程。
            cacheLock.EnterUpgradeableReadLock();
            try
            {
                string result = null;
                if (innerCache.TryGetValue(key, out result))
                {
                    if (result == value)
                    {
                        return AddOrUpdateStatus.Unchanged;
                    }
                    else
                    {
                        //升級(jí)成寫(xiě)鎖,其他所有線(xiàn)程都被阻塞。
                        cacheLock.EnterWriteLock();
                        try
                        {
                            innerCache[key] = value;
                        }
                        finally
                        {
                            //退出寫(xiě)鎖,允許其他讀線(xiàn)程。
                            cacheLock.ExitWriteLock();
                        }
                        return AddOrUpdateStatus.Updated;
                    }
                }
                else
                {
                    cacheLock.EnterWriteLock();
                    try
                    {
                        innerCache.Add(key, value);
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                    return AddOrUpdateStatus.Added;
                }
            }
            finally
            {
                //退出升級(jí)鎖。
                cacheLock.ExitUpgradeableReadLock();
            }
        }

        public enum AddOrUpdateStatus
        {
            Added,
            Updated,
            Unchanged
        };
    }

四:總結(jié)

多線(xiàn)程實(shí)際開(kāi)發(fā)當(dāng)中,往往測(cè)試沒(méi)問(wèn)題,一到生產(chǎn)環(huán)境,并發(fā)高了就容易出問(wèn)題, 一定注意。

本文參考CLR via C#。

相關(guān)文章

  • C# cefSharep控件的使用詳情

    C# cefSharep控件的使用詳情

    本文主要介紹了C# cefSharep控件的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • TortoiseSVN使用教程

    TortoiseSVN使用教程

    TortoiseSVN 是 Subversion 版本控制系統(tǒng)的一個(gè)免費(fèi)開(kāi)源客戶(hù)端,可以超越時(shí)間的管理文件和目錄。本文給大家介紹TortoiseSVN使用教程,對(duì)tortoisesvn使用相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • c#之事件用法

    c#之事件用法

    這篇文章介紹了c#中事件的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#中的Timer和DispatcherTimer使用實(shí)例

    C#中的Timer和DispatcherTimer使用實(shí)例

    這篇文章主要介紹了C#中的Timer和DispatcherTimer使用實(shí)例,本文分別給出它們的使用代碼實(shí)例,需要的朋友可以參考下
    2015-01-01
  • unity實(shí)現(xiàn)翻頁(yè)按鈕功能

    unity實(shí)現(xiàn)翻頁(yè)按鈕功能

    這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)翻頁(yè)按鈕功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C#實(shí)現(xiàn)在Excel中添加篩選器并執(zhí)行篩選的操作

    C#實(shí)現(xiàn)在Excel中添加篩選器并執(zhí)行篩選的操作

    自動(dòng)篩選器是 Excel 中的一個(gè)基本但極其有用的功能,它可以讓你根據(jù)特定的條件來(lái)自動(dòng)隱藏和顯示你的數(shù)據(jù),當(dāng)有大量的數(shù)據(jù)需要處理時(shí),這個(gè)功能可以幫你快速找到你需要的信息,下面將介紹如何使用免費(fèi).NET Excel庫(kù)在Excel中添加、應(yīng)用和刪除自動(dòng)篩選器,需要的朋友可以參考下
    2024-05-05
  • C#中通過(guò)API實(shí)現(xiàn)的打印類(lèi) 實(shí)例代碼

    C#中通過(guò)API實(shí)現(xiàn)的打印類(lèi) 實(shí)例代碼

    這篇文章介紹了,C#中通過(guò)API實(shí)現(xiàn)的打印類(lèi) 實(shí)例代碼,有需要的朋友可以參考一下
    2013-08-08
  • C# 的關(guān)鍵字詳細(xì)介紹

    C# 的關(guān)鍵字詳細(xì)介紹

    本文將詳細(xì)介紹C#關(guān)鍵字的應(yīng)用,可供有需要的朋友參考
    2012-11-11
  • 結(jié)合.net框架在C#派生類(lèi)中觸發(fā)基類(lèi)事件及實(shí)現(xiàn)接口事件

    結(jié)合.net框架在C#派生類(lèi)中觸發(fā)基類(lèi)事件及實(shí)現(xiàn)接口事件

    這篇文章主要介紹了結(jié)合.net框架在C#派生類(lèi)中觸發(fā)基類(lèi)事件及實(shí)現(xiàn)接口事件,示例的事件編程中包括接口和類(lèi)的繼承等面向?qū)ο蟮幕A(chǔ)知識(shí),需要的朋友可以參考下
    2016-02-02
  • c#測(cè)試反射性能示例

    c#測(cè)試反射性能示例

    這篇文章主要介紹了c#測(cè)試反射性能示例,Activator.CreateInstance和AssemblyCreateInstance性能測(cè)試,需要的朋友可以參考下
    2014-03-03

最新評(píng)論

无锡市| 和顺县| 赤壁市| 昌邑市| 闽侯县| 西平县| 肥东县| 广水市| 庆元县| 临城县| 锡林郭勒盟| 文昌市| 襄城县| 库尔勒市| 阿合奇县| 连云港市| 肥乡县| 鸡泽县| 青冈县| 绵阳市| 黄大仙区| 鹿邑县| 潞城市| 罗源县| 乌拉特后旗| 崇文区| 来宾市| 广南县| 准格尔旗| 梧州市| 嘉定区| 永和县| 红原县| 井陉县| 伽师县| 汾西县| 乌拉特中旗| 出国| 三原县| 合江县| 揭西县|