2013-04-08 72 views
9

我想在C#中的列表中增加一個元素,但我需要它是線程安全的,因此計數不會受到影響。線程安全在C中增加#

我知道你能爲整數做到這一點:

Interlocked.Increment(ref sdmpobjectlist1Count);

但這並不在列表上工作,我已在迄今爲止以下內容:

lock (padlock) 
{ 
    DifferenceList[diff[d].PropertyName] = DifferenceList[diff[d].PropertyName] + 1; 
} 

我知道這工作,但我不確定是否有另一種方法來做到這一點?

+14

爲什麼你需要另一種方式,如果這種方式有效? – 2013-04-08 20:22:29

+0

您是否在尋找非排他性的鎖定機制? – 2013-04-08 20:24:01

+0

http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx – CSharpie 2013-04-08 20:24:18

回答

1

正如David Heffernan所說,ConcurrentDictionary應該提供更好的性能。但是,取決於多線程嘗試訪問緩存的頻率,性能增益可能可以忽略不計。

using System; 
using System.Collections.Concurrent; 
using System.Threading; 

namespace ConcurrentCollections 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var cache = new ConcurrentDictionary<string, int>(); 

      for (int threadId = 0; threadId < 2; threadId++) 
      { 
       new Thread(
        () => 
        { 
         while (true) 
         { 
          var newValue = cache.AddOrUpdate("key", 0, (key, value) => value + 1); 
          Console.WriteLine("Thread {0} incremented value to {1}", 
           Thread.CurrentThread.ManagedThreadId, newValue); 
         } 

        }).Start(); 
      } 

      Thread.Sleep(TimeSpan.FromMinutes(2)); 
     } 
    } 
} 
+0

更新函數在AddOrUpdate調用中不是原子的。 https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110)。aspx – Ryan 2015-06-03 17:01:01

+0

該註釋僅僅意味着「代碼在成功之前可能會運行多次」。它基本上在鎖外運行。所以它得到現有的值,加1,取出一個鎖,然後嘗試寫回。如果現有值在此期間發生變化,它會重複此過程,直至成功。 – mjwills 2017-06-19 23:18:51

-1

檢查您鎖定在「padLock」上的變量,通常情況下,您可以將其定義爲private static Object padLock = new Object()。如果您沒有將其定義爲靜態,則每個對象都有自己的副本,因此它不起作用。

+4

這取決於數據。如果數據不是靜態的,那麼就不需要鎖對象是靜態的;你會不必要的同步線程,而不是試圖訪問相同的數據。 – Servy 2013-04-08 20:36:25

1

如果使用List<int[]>而非List<int>,並在列表中的每個元素是一個單一項目數組,你將能夠做到Increment(ref List[whatever][0]),並將它是原子的。人們可以提高存儲效率,如果稍有一個定義

class ExposedFieldHolder<T> {public T Value;} 

,然後使用List<ExposedFieldHolder<int>>和所使用的語句Increment(ref List[whatever].Value)進行增量。如果內置類型提供了將項目公開爲ref或允許派生類充分訪問其內部以便自己提供此類功能的方法,則事情可能會更有效。然而,他們不需要從頭開始定義自己的集合類型,或者將每個項目封裝在自己的類對象中[使用數組或封裝類]。

+0

除非在大多數情況下編寫自己的線程安全集合有一些非常具體的原因,否則使用TPL提供的一個更好。 – 2013-04-08 22:49:18