<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【不小心就會犯錯】 .NET的ConcurrentDictionary,線程安全集合類

      ConcurrentDictionary 是.NET 4.0里面新增的號稱線程安全的集合類。

      那么自然,我們會預期ConcurrentDictionary 中的代碼是線程安全的(至少幾個關鍵方法是線程安全的).

      舉個例子,使用者可能會預期GetOrAdd中的方法當Key不存在的時候只執行一次Add的委托,第二次調用GetOrAdd就應該直接取回剛才生成的值了.

      參考一下以下代碼:

              public static  void Test()
      {
      var concurentDictionary = new ConcurrentDictionary<int, int>();

      var w = new ManualResetEvent(false);
      int timedCalled = 0;
      var threads = new List<Thread>();
      for (int i = 0; i < Environment.ProcessorCount; i++)
      {
      threads.Add(new Thread(() =>
      {
      w.WaitOne();
      concurentDictionary.GetOrAdd(1, i1 =>
      {
      Interlocked.Increment(ref timedCalled);
      return 1;
      });
      }));
      threads.Last().Start();
      }

      w.Set();//release all threads to start at the same time
      Thread.Sleep(100);
      Console.WriteLine(timedCalled);// output is 4, means call initial 4 times
      //Console.WriteLine(concurentDictionary.Keys.Count);
      }

      GetOrAdd方法的定義就是按照Key獲取一個Value,如果Key不存在,那么調用Func<T> 添加一個鍵值對.

      按照ConcurrentDictionary的定義,  我預期這個Add應該只被調用一次

      可是上面那段代碼的運行結果表明, Interlocked.Increment(ref timedCalled); 被調用了4次,真是尷尬啊

       

      用于初始化值的委托還真的是可以多次執行的,所以

      • 要么保證委托中的代碼重復執行不會有問題
      • 要么使用線程安全的初始化方法,例如Lazy<T> 

       

       public static void Test()
      {
      var concurentDictionary = new ConcurrentDictionary<int, int>();

      var w = new ManualResetEvent(false);
      int timedCalled = 0;
      var threads = new List<Thread>();
      Lazy<int> lazy = new Lazy<int>(() => { Interlocked.Increment(ref timedCalled); return 1; });
      for (int i = 0; i < Environment.ProcessorCount; i++)
      {
      threads.Add(new Thread(() =>
      {
      w.WaitOne();
      concurentDictionary.GetOrAdd(1, i1 =>
      {
      return lazy.Value;
      });
      }));
      threads.Last().Start();
      }

      w.Set();//release all threads to start at the same time
      Thread.Sleep(100);
      Console.WriteLine(timedCalled);// output is 1
      }

       

      附: 注釋中也不說一下這個初始化方法會被多次調用,如果不是偶然遇到這個問題,估計永遠都不知道

       //
      // Summary:
      // Adds a key/value pair to the System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue>
      // if the key does not already exist.
      //
      // Parameters:
      // key:
      // The key of the element to add.
      //
      // valueFactory:
      // The function used to generate a value for the key
      //
      // Returns:
      // The value for the key. This will be either the existing value for the key
      // if the key is already in the dictionary, or the new value for the key as
      // returned by valueFactory if the key was not in the dictionary.
      //
      // Exceptions:
      // System.ArgumentNullException:
      // key is a null reference (Nothing in Visual Basic).-or-valueFactory is a null
      // reference (Nothing in Visual Basic).
      //
      // System.OverflowException:
      // The dictionary contains too many elements.

       

      該集合類中所有使用Func<T>的方法也存在類似的問題

      希望能給還不知道該問題的朋友提個醒,避免不必要的BUG

      posted on 2011-11-21 11:51  聽說讀寫  閱讀(22296)  評論(14)    收藏  舉報

      導航

      主站蜘蛛池模板: 国产男女猛烈无遮挡免费视频网站 | 国产成人精品无码一区二区| 国产麻豆一区二区精彩视频| 久久天天躁综合夜夜黑人鲁色| 精品偷拍一区二区三区| 精品伊人久久久香线蕉| 国产精品久久久久久久9999| 国产高潮又爽又刺激的视频| 欧美大bbbb流白水| 国产二区三区不卡免费| 夜夜爽77777妓女免费看| 免费的很黄很污的视频| 一区二区偷拍美女撒尿视频| 人妻熟女一区二区aⅴ向井蓝| 国产精品黄色一区二区三区| 亚洲二区中文字幕在线| 午夜成年男人免费网站| 中文字幕国产日韩精品| 国产一卡2卡三卡4卡免费网站| 亚洲欧洲一区二区精品| h无码精品3d动漫在线观看| 含紧一点h边做边走动免费视频| 国产精品 无码专区| 小金县| 亚洲色偷偷偷网站色偷一区| 亚洲国模精品一区二区| 无码熟妇人妻av在线电影| 国产短视频精品一区二区| 亚洲国产一区二区三区久| 日韩一区二区在线观看的| 一本av高清一区二区三区| 色欲国产精品一区成人精品| 漂亮的保姆hd完整版免费韩国| 国产喷水1区2区3区咪咪爱AV| 国产高清亚洲一区亚洲二区| 久久久久青草线综合超碰| 国内精品人妻一区二区三区| 色偷偷www.8888在线观看| 商洛市| 东京热高清无码精品| 亚洲人精品午夜射精日韩|