ConcurrentDictionary與Dictionary 替換


本文導讀:ASP.NET中ConcurrentDictionary是.Net4 增加的,相對於Dictionary的線程安全的集合, ConcurrentDictionary可實現一個線程安全的集合,可以由多個線程同時並發讀寫Key-value,與Dictionary的區別主要有以下幾點

一、Dictionary<TKey, TValue>

1、泛型類提供了從一組鍵到一組值的映射。通過鍵來檢索值的速度是非常快的,這是因為 Dictionary<TKey,TValue> 類是作為一個哈希表來實現的。檢索速度取決於為 TKey 指定的類型的哈希算法的質量。

2、TValue可以是值類型,數組,類或其他。

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

4、若允許多個線程對集合執行讀寫操作,您必須實現自己的同步,讀寫並行的時候需要加鎖,但是加上鎖性能就會受影響。

 

二、ConcurrentDictionary<TKey, TValue>

1、表示可由多個線程同時訪問的鍵/值對的線程安全集合。

2、ConcurrentDictionary是.net4.0推出的一套線程安全集合里的其中一個,和它一起被發行的還有

ConcurrentStack,ConcurrentQueue等類型,它們的單線程版本(線程不安全的,Queue,Stack,Dictionary)。

3、用法同Dictionary很多相同,但是多了一些方法。ConcurrentDictionary 屬於System.Collections.Concurrent 命名空間

 

三、ConcurrentDictionary與Dictionary的區別實例

 

在多線程環境下,下面實例判斷Key是否存

 

 
C# 代碼    復制
public class Program
    {
        static Dictionary<string, Logger> loggreDic;
        static object loggerDicLocker = new object();
        public static void Main()
        {  loggreDic = new Dictionary<string, Logger>();  for (int i = 0; i < 100; i++)  {  ThreadPool.QueueUserWorkItem(o =>  {  try  {  var logger = GetLogger("AAA");  }  catch (Exception)  {  Console.WriteLine(string.Format("第{0}個線程出現問題", o));  }   }, i);  }  Console.ReadKey();  }   static Logger GetLogger(string cmdId)  {  if (!loggreDic.ContainsKey(cmdId))  {  loggreDic.Add(cmdId, LogManager.GetLogger(string.Format("AAA.{0}", cmdId)));  }  return loggreDic[cmdId];  }  } 

在GetLogger的地方做了判斷的處理,但是在多線程的時候還是會報 已添加了具有相同鍵的項 的錯誤。原因是在Dictionary中加了重復的Key造成的。

 

解決方法

可以用ConcurrentDictionary 替代Dictionary

 

 
C# 代碼    復制
    public interface IGetLogger
    {
        Logger GetLogger(string cmdId);
    }

    public class ConcurrentDictionaryLogger : IGetLogger
    {  ConcurrentDictionary<string, Logger> loggreDic = new ConcurrentDictionary<string, Logger>();  public Logger GetLogger(string cmdId)  {  if (!loggreDic.ContainsKey(cmdId))  {  loggreDic.TryAdd(cmdId, LogManager.GetLogger(string.Format("AAA.{0}", cmdId)));  }  return loggreDic[cmdId];  }  }   public static void Main()  {  IGetLogger conLogger = new ConcurrentDictionaryLogger();   IGetLogger lockerLogger = new LockerDictionaryLogger();   CodeTimer.Time("使用ConcurrentDictionary", 1000000, () =>  {  ThreadPool.QueueUserWorkItem(o =>  {  try  {  var logger = conLogger.GetLogger("AAA");  if (logger == null)  {  Console.WriteLine(string.Format("{0}個線程獲取到的值是 NULL", o));  }  }  catch (Exception ex)  {  Console.WriteLine(string.Format("第{0}個線程出現問題, {1}", o, ex.Message));  }  });  });  }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM