在ConcurrentDictionary中更新元素时​​出现同步问题

时间:2014-12-03 06:34:24

标签: c# .net multithreading

我有这个代码,我试图在我的并发字典中更新项目(这是一个列表)的密钥(密钥始终相同)。

这是我的代码 - :

class Program
    {
        private static readonly ConcurrentDictionary<string, List<int>> s_mapDatatypeToSource = new ConcurrentDictionary<string, List<int>>();
        static void Main(string[] args)
        {


                try
                {
                    Parallel.For(0, 10000000, i => AddItemToList(i, "local"));
                }
                catch (Exception exception)
                {
                    Console.WriteLine(string.Format("Exception thrown ...{0}", exception.Message));
                    Console.ReadLine();
                    throw;
                }

            Console.WriteLine("Completed without exception");
            Console.ReadLine();

        }

        private static void AddItemToList(int dataKey, string sourceName)
        {
            s_mapDatatypeToSource.AddOrUpdate(sourceName.ToUpperInvariant(), new List<int> { dataKey }, (s, list) =>
            {

                {
                    list.Add(dataKey);
                    return list;
                }


            });

        }
    }

代码中有十分之一的代码抛出异常 - “源数组不够长。检查srcIndex和长度,以及数组的下限。”

我知道这是list的同步问题,但我不明白为什么会这样,因为ConcurrentDictionary是线程安全的。所以我假设,它只允许一个线程一次更新我的列表,所以应该没有任何问题 - :

我知道我遗失了一些东西 - 建议请 - :

1 个答案:

答案 0 :(得分:4)

ConcurrentDictionary可以是线程安全的,但List不是。

从List中看反编译方法:

public void Add(T item)
{
  if (this._size == this._items.Length)
    this.EnsureCapacity(this._size + 1);
  this._items[this._size++] = item;
  ++this._version;
}

线程#1和Thead#2可以同时传递if (this._size == this._items.Length)。线程#1将在此设置值this._items[this._size++] = item;,但线程#2将导致IndexOutOfRangeException。你需要线程安全列表。

更新您可以使用SynchronizedCollection代替列表