9

我正在尝试在 C# 的列表中增加一个元素,但我需要它是线程安全的,因此计数不会受到影响。

我知道您可以对整数执行此操作:

Interlocked.Increment(ref sdmpobjectlist1Count);

但这不适用于列表我到目前为止有以下内容:

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

我知道这行得通,但我不确定是否有其他方法可以做到这一点?

4

3 回答 3

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));
        }
    }
}
于 2013-04-08T21:56:05.320 回答
1

如果您使用 aList<int[]>而不是 a List<int>,并且列表中的每个元素都是一个单项数组,那么您将能够做到Increment(ref List[whatever][0])并使其成为原子的。如果定义一个可以稍微提高存储效率

class ExposedFieldHolder<T> {public T Value;}

然后使用 a List<ExposedFieldHolder<int>>and 语句Increment(ref List[whatever].Value)来执行增量。如果内置类型提供了一种将项目公开为 a 的方法,ref或者允许派生类对它们的内部进行足够的访问以自己提供这种能力,那么事情可能会更有效。但是,它们没有,因此必须要么从头开始定义自己的集合类型,要么将每个项目封装在其自己的类对象中[使用数组或包装类]。

于 2013-04-08T22:10:36.797 回答
-1

检查您锁定在“padLock”上的变量,通常,您可以将其定义为private static Object padLock = new Object(). 如果您不将其定义为静态,则每个对象都有自己的副本,因此它将不起作用。

于 2013-04-08T20:34:48.630 回答