2016-03-04 21 views
1

例如,我有這樣的代碼:如何使用ImmutableList <>來代替List <>來獲得線程安全性?

using System; 
using System.Collections.Concurrent; 
using System.Collections.Generic; 
using System.Collections.Immutable; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ConsoleApplication2 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var lst =new List<int>(); 
     for (int i = 0; i < 2000000; i++) 
     { 
      lst.Add(i); 
     } 

     new Thread(() => 
     {     
      for (int i = 20000001; i < 21000000; i++) 
      { 
       lst.Add(i); 
      } 

     }).Start(); 
     new Thread(() => 
     { 
      lst.Where(item => 
        item > 85200 && item < (50000 * (item + 154896556) * 2/1000) 
      ).ToList(); 

     }).Start(); 

     new Thread(() => 
     { 
      for (int i = 21000001; i < 22000000; i++) 
      { 
       lst.Add(i); 
      } 

     }).Start(); 
    } 
} 
} 

和我得到這個異常(附加信息:集合已修改;枚舉操作可能不會執行。),因爲我在一個線程LST變化,在另一個線程迭代。 這是我的問題:如何重寫此代碼通過System.Collections.Immutable.ImmutableList <>而不是列表<>?

+0

考慮使用ConcurrentBag 不是List 的。列表不是線程安全,而ConcurrentBag是。 –

+0

ImmutaleList呢? –

回答

0

您確定要ImmutableList <>嗎?引用文檔:

當您添加或刪除不可變列表中的項目時,原始列表的副本將與添加或刪除的項目一起進行,並且原始列表保持不變。

...

,如果它已經包含了指定的對象,它返回一個新的不可變列表與對象添加,或者當前的列表。

嘗試,而不是在那裏你在鎖(名單){}塊編輯列表,如包裝的任何實例:

lock(lst) 
{ 
    list.Add(i); 
} 

您將有一個(可能是很輕微的)性能損失時您的代碼嘗試從列表<>中讀取,但它被鎖定以進行編輯,但它應該是線程安全的。

+1

我更喜歡在我的代碼中不使用鎖,因爲我的代碼非常複雜,並且包含許多共享列表和許多一起工作的線程。 其實我這樣做,我面臨死鎖和非常複雜的問題。 但我聽說過ImmutableList,我想這可能是我的正確方法。 –

+4

@ S.Cheginy:如果問題是代碼複雜,大量內存在大量線程間共享,解決方法是不放棄鎖定。解決方案是使程序更簡單,使用更少的線程,跨線程共享更少的內存,並使用更多的鎖。共享內存多線程很難。考慮一種基於任務的方法。讓TPL爲您管理線程。 –

+2

不可變列表不能避免需要鎖定。同時調用兩個'MyList = MyList.add(NewElement)'可能只會添加一個元素。這不會破壞你的列表,但你的程序狀態現在不一致。當你嘗試修復這些錯誤時(例如,通過檢測它們),編譯器往往會與你發生衝突;只要這些謊言在單線程程序中是無法檢測到的,它就可以向你「說謊」發生了什麼事情。你可以嘗試通過引入記憶障礙來防止這種謊言。但是,這仍然存在其他問題(作爲非專家,我不知道他們是什麼)。 – Brian

2

爲了獲得線程安全的,也有大量的線程安全的集合,你可以使用:

  • BlockingCollection
  • ConcurrentDictionary
  • ConcurrentQueue
  • ConcurrentStack
  • ConcurrentBag

你可以ev連接使用IProducerConsumerCollection

這裏所有的記錄實現自己: https://msdn.microsoft.com/en-us/library/dd997305(v=vs.110).aspx

相關問題