.Net4后ConcurrentDictionary替換Dictionary測(cè)試
在.NET Framework 4.0中,增加了ConcurrentDictionary。ConcurrentDictionary<TKey, TValue> 繼承自 Dictionary<TKey, TValue>,因此它支持大部分標(biāo)準(zhǔn)的字典操作,如添加、查找、刪除等。但是,它還提供了一些額外的線程安全方法,比如 TryAdd, TryUpdate, TryRemove 等。
前言
Dictionary<TKey, TValue>
1、泛型類提供了從一組鍵到一組值的映射。通過鍵來檢索值的速度是非常快的,這是因?yàn)?Dictionary<TKey,TValue> 類是作為一個(gè)哈希表來實(shí)現(xiàn)的。檢索速度取決于為 TKey 指定的類型的哈希算法的質(zhì)量。
2、TValue可以是值類型,數(shù)組,類或其他。
3、一個(gè)類的實(shí)例里,有個(gè)屬性是個(gè)字典,我們不加考慮的會(huì)用Dictionary,而當(dāng)這個(gè)屬性被提升為static靜態(tài)的(類級(jí)別的)時(shí)候,我們就要考慮它的線程安全性了,因?yàn)樗锌赡鼙欢鄠€(gè)線程同時(shí)訪問,當(dāng)然,如果這個(gè)對(duì)象是只讀的,也無所謂線程安全,但如果這個(gè)屬性是可以被寫的,那就需要把它加鎖了。
4、若允許多個(gè)線程對(duì)集合執(zhí)行讀寫操作,您必須實(shí)現(xiàn)自己的同步,讀寫并行的時(shí)候需要加鎖,但是加上鎖性能就會(huì)受影響。
ConcurrentDictionary<TKey, TValue>
1、表示可由多個(gè)線程同時(shí)訪問的鍵/值對(duì)的線程安全集合。
2、ConcurrentDictionary是.net4.0推出的一套線程安全集合里的其中一個(gè),和它一起被發(fā)行的還有ConcurrentStack,ConcurrentQueue等類型,它們的單線程版本(線程不安全的,Queue,Stack,Dictionary)。
3、用法同Dictionary很多相同,但是多了一些方法。ConcurrentDictionary 屬于System.Collections.Concurrent 命名空間
ConcurrentDictionary實(shí)例測(cè)試
在.NET4.0以前,在多線程環(huán)境下如果我們使用Dictionary類,只能自己編碼實(shí)現(xiàn)線程同步來保證線程安全,別無他選。在.NET4.0以后微軟替我們開發(fā)了ConcurrentDictionary類,如果你使用字典遇到線程安全的問題,那么就使用ConcurrentDictionary類,不用再考慮“Dictionary+Locks”的問題了。
下面我們對(duì)比來看看加鎖后的Dictionary和ConcurrentDictionary的使用情況,是否解決了問題下,性能如何呢?
string res = "";
var concurrentDictionary = new ConcurrentDictionary<int, string>();
var dictionary = new Dictionary<int, string>();
dictionary.TryAdd(1, "aa");
concurrentDictionary.TryAdd(1,"");
var sw = new Stopwatch();
sw.Start();
Parallel.For(0, 1000000, i =>//Parallel使用并行循環(huán)
{
lock (dictionary)
{
dictionary[i] = new Random().Next(1000, 9999).ToString();
}
});
sw.Stop();
Console.WriteLine("加鎖寫入dictionary {0}", sw.Elapsed);
//wrinting to dictionary with a lock: 00:00:00.0633939
sw.Restart();
Parallel.For(0, 1000000, i =>
{
concurrentDictionary[i] = new Random().Next(1000, 9999).ToString();
});
sw.Stop();
Console.WriteLine("concurrentdictionary寫入時(shí)長 : {0}", sw.Elapsed);
sw.Restart();
Parallel.For(0, 1000000, i =>
{
lock (dictionary)
{
res = dictionary[i];
}
});
sw.Stop();
Console.WriteLine("讀取dictionary耗時(shí): {0}", sw.Elapsed);
sw.Restart();
Parallel.For(0, 1000000, i =>
{
res = concurrentDictionary[i];
});
sw.Stop();
Console.WriteLine("讀取concurrentdictionary耗時(shí): {0}", sw.Elapsed);
Console.ReadLine();結(jié)果如下

ConcurrentDictionary和Dictionary運(yùn)行結(jié)果顯示,讀取寫入的效率都是ConcurrentDictionary勝出,完美,也未出現(xiàn)線程安全的問題。注意環(huán)境關(guān)系可能略有差距。據(jù)說在多核多線程的情況下concurrentDictionary將有更好的性能表現(xiàn)。
面試官也可能問Dictionary怎么解決線程安全問題,如果答出使用ConcurrentDictionary一定是加分項(xiàng)。
注意,有網(wǎng)友指出ConcurrentDictionary使用依然會(huì)有線程安全問題,樓主目前沒有發(fā)現(xiàn),大家可以自己試一試。
小妙招
tryadd的使用,在字典中添加的時(shí)候,集合里已經(jīng)包含了指定的key,Add方法會(huì)出錯(cuò),拋出異常,如果使用tryadd就會(huì)避免這個(gè)問題,添加失敗會(huì)返回false。
dictionary.TryAdd(1, "aa"); concurrentDictionary.TryAdd(1,"");
注意ConcurrentDictionary只支持TryAdd,普通Dictionary的TryAdd和Add都支持。
到此這篇關(guān)于.Net4后ConcurrentDictionary替換Dictionary測(cè)試的文章就介紹到這了,更多相關(guān).Net4后ConcurrentDictionary替換Dictionary內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MVC+EasyUI+三層新聞網(wǎng)站建立 建站準(zhǔn)備工作(一)
這篇文章主要為大家詳細(xì)介紹了MVC+EasyUI+三層新聞網(wǎng)站建立的第一篇,建站的準(zhǔn)備工作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Entity Framework Core延遲加載(懶加載)用法
這篇文章介紹了Entity Framework Core延遲加載(懶加載)的使用方式,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
asp.net導(dǎo)出excel數(shù)據(jù)的常見方法匯總
這篇文章主要介紹了asp.net導(dǎo)出excel數(shù)據(jù)的常見方法,實(shí)例匯總了數(shù)據(jù)導(dǎo)出的常見的方法以及相關(guān)的注意事項(xiàng),是非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10
Windows Server 2012 R2 Standard搭建ASP.NET Core環(huán)境圖文教程
這篇文章主要介紹了Windows Server 2012 R2 Standard搭建ASP.NET Core環(huán)境圖文教程,需要的朋友可以參考下2016-07-07
asp.net 從POST的數(shù)據(jù)流中提取參數(shù)和文件
按理,F(xiàn)orm提交的數(shù)據(jù),無論是application/x-www-form-urlencoded還是multipart/form-data(有附件時(shí)),都可在服務(wù)端通過Request.Form["name"]和Request.Files["name"]獲取到參數(shù)和上傳的文件。2010-02-02

