我正在尝试使用C#增加列表中的元素,但我需要它是线程安全的,因此计数不会受到影响。
我知道你可以为整数做这个:
Interlocked.Increment(ref sdmpobjectlist1Count);
但是到目前为止我对以下内容的列表不起作用:
lock (padlock)
{
DifferenceList[diff[d].PropertyName] = DifferenceList[diff[d].PropertyName] + 1;
}
我知道这有效,但我不确定是否还有其他方法可以做到这一点?
答案 0 :(得分: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));
}
}
}
答案 1 :(得分: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
或允许的派生类充分访问其内部,以便自己提供这样的能力,那么事情可能会更有效率。但是,它们不是必须从头开始定义一个自己的集合类型,或者将每个项封装在它自己的类对象中[使用数组或包装类]。
答案 2 :(得分:-1)
检查锁定在“padLock”上的变量,通常,您可以将其定义为private static Object padLock = new Object()
。如果你没有将它定义为静态,每个对象都有自己的副本,因此它不起作用。