2013-04-08 74 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