非同步與並行~List<T>是執行緒安全的嗎?

張佔嶺發表於2016-12-08

返回目錄

題目有點意思,大家都知道Dictionary<K,V>不是執行緒安全的型別,而List<T>是執行緒安全的嗎?在今天之前大叔沒有去測試過,而就在今天也是一個VIP問我,說在我的程式碼中使用了並行,然後為一個List賦值,說的直接一點就是:List元素是全域性的,在各個執行緒裡分別去操作它,測試資料是1萬條,而在測試結果之後,我發展List元素最終的陣列是9000多條,也就是說被併發了幾千條資料,呵呵,下面我們們看一下原始碼吧!

測試程式碼:

     [TestMethod]
        public void TestMethod0()
        {
            List<int> intList = new List<int>();
            var result = Parallel.ForEach(Enumerable.Range(1, 10000), (val) =>
            {
                intList.Add(val);
            });
            if (result.IsCompleted)
            {
                Console.WriteLine("intList.Count():" + intList.Count);
            }
        }

我們們看一下單元測試的結果,大叔一直很喜歡這句話:機器最能證明一切!

通過截圖我們可以看到,陣列的長度並不是1萬,而被丟失了一些陣列,這就是併發,這就是執行緒的不安全!

下面大家使用被封裝的ConcurrentList執行緒安全的物件,再進行一下測試:

     [TestMethod]
        public void TestMethod1()
        {
            ConcurrentList<int> intList = new ConcurrentList<int>();
            var result = Parallel.ForEach(Enumerable.Range(1, 10000), (val) =>
            {
                intList.Add(val);
            });
            if (result.IsCompleted)
            {
                Console.WriteLine("intList.Count():" + intList.Count);
            }
        }

再看一下測試的結果,它與原始的1萬條資料是相同的

對於執行緒安全的型別,多執行緒併發訪問操作List元素時,其它執行緒被鎖定,保證了List物件的安全,同時也保證了結果的正確性。

返回目錄

相關文章