如何正确锁定集合

How to properly lock a collection

我一直在努力思考锁的问题,但我似乎无法弄清楚。 下面的代码使用了锁,但仍然给出 'collection was modified' 错误。我错过了什么?


    class Program
    {
        static List<int> lEntries = new List<int>();
        static readonly object entriesLock = new object();

        public static List<int> Entries {
            get { lock (entriesLock) { return lEntries; } }
            set { lock (entriesLock) { lEntries = value; } }
        }

        static void Main(string[] args)
        {
            // Run 20 times to reproduce the issue more often
            for (int i = 0; i < 20; i++)
            {
                Task.Run(() =>
                {
                    for (int j = 0; j < 10000; j++)
                    {
                        Entries.Add(j);
                    }
                });

                Task.Run(() =>
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        Entries.Average(); // System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'
                    }
                });
            }

            Console.ReadLine();
        }
    }


锁仅在其范围内有效。

lock (entriesLock)
{
  //safe to access here.
}
// no longer safe

因此,不幸的是,您尝试返回锁定列表是没有意义的,因为当 getter/setter 离开时锁定会立即过期。实际访问列表时使用外面的锁。

for (int j = 0; j < 10000; j++)
{
  lock (entriesLock)
  {
    lEntries.Add(j);
  }
}

// or

lock (entriesLock)
{
  for (int j = 0; j < 10000; j++)
  {
    lEntries.Add(j);
  }
}