C#中的线程安全增量

时间:2013-04-08 20:21:25

标签: c# multithreading thread-safety increment

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

我知道你可以为整数做这个:

Interlocked.Increment(ref sdmpobjectlist1Count);

但是到目前为止我对以下内容的列表不起作用:

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

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

3 个答案:

答案 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()。如果你没有将它定义为静态,每个对象都有自己的副本,因此它不起作用。