程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 的 Dictionary 使用上應注意事項,

C# 的 Dictionary 使用上應注意事項,

編輯:C#入門知識

C# 的 Dictionary 使用上應注意事項,


一個已上線、用戶龐大的系統,幾個月來第一次出現這個系統錯誤訊息 :

「已經加入含有相同索引鍵的項目」
An item with the same key has already been added.

分析原因:

C# 的 Dictionary 這種資料結構的變數,若宣告為 static,在使用上,要注意寫入或 Add 資料前,只作 if ContainsKey 判斷是不夠的 (如下圖 2),因其不是「執行緒 ; 線程 (thread)」安全的 (若有多人同時寫入,有可能造成異常,甚至出錯。機率不高,但久久偶爾會發生一次)。

因此在 Dictionary 寫入或 Add 前,應多做一個 lock 的動作,如下圖 3,以達到一次只有一個人 (一個執行緒),能進入 lock 區塊中,其他人要排隊等候。

 


圖 1 宣告 Dictionary 變數



圖 2 改寫前 (久久偶爾會發生一次錯誤的寫法)



圖 3 改寫後


C# 的 lock,
但注意一定要是宣告為 static 的變數,才有效
(static 變數,表示全網站的所有使用者,共用同一塊記憶體,而不是每個使用者各自 new 一塊記憶體)。

-------------------------------------------------------------------
Dictionary 介紹 (msdn) :
https://msdn.microsoft.com/zh-tw/library/xfhwa508(v=vs.110).aspx
-------------------------------------------------------------------
詳細說明 Dictionary 問題的文章 (推薦):
http://blog.darkthread.net/post-2012-01-31-dictionary-thread-safe.aspx

上文中,提到 .NET 4.0 加入一種新的 System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>,
不見得能解決此問題,建議勿用。
-------------------------------------------------------------------
lock 介紹 :
http://www.dotblogs.com.tw/yc421206/archive/2011/01/07/20624.aspx
https://msdn.microsoft.com/zh-tw/library/c5kehkcz.aspx
-------------------------------------------------------------------
ConcurrentDictionary<TKey, TValue> 類別 :
https://msdn.microsoft.com/zh-tw/library/dd287191(v=vs.110).aspx

ConcurrentDictionary<TKey, TValue>.GetOrAdd 方法 (TKey, TValue) :
https://msdn.microsoft.com/zh-tw/library/ee378674(v=vs.110).aspx

Dictionary + Locking versus ConcurrentDictionary
http://www.codeproject.com/Articles/548406/Dictionary-plus-Locking-versus-ConcurrentDictionar
-------------------------------------------------------------------
ConcurrentDictionary 讓你的多線程代碼更優美
http://www.bkjia.com/C_jc/968538.html

用Dictionary,而當這個屬性被提升為static靜態的(類級別的)時候,我們就要考慮它的線程安全性了,因為它有可能被多個線程同時訪問,當然,如果這個對象是只讀的,也無所謂線程安全,但如果這個屬性是可以被寫的,那就需要把它加鎖了。

但從性能上看,就不能被接收,我們知道,lock會把其它線程鎖在外面,無論是讀還是寫,都會被鎖,性能非常差。
-------------------------------------------------------------------

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved