繁体   English   中英

在C#中克隆ConcurrentDictionary时应该使用锁对象吗?

[英]Should I use a lock object while Cloning a ConcurrentDictionary in C#?

我有一个代码库,其中多个线程正在ConcurrentDictionary中编写,每60秒另一个线程运行并克隆主CD,将其清除,然后继续在克隆的CD上工作。 我想知道如果我在Cloning and Clearing主CD时不使用lock会丢失一些数据吗? 演示此问题的代码如下:


class Program
    {
        static object lock_obj = new object();

        static async Task Main(string[] args)
        {
            ConcurrentDictionary<string, ThreadSafeLong> cd = new ConcurrentDictionary<string, ThreadSafeLong>();


            Func<Task> addData = () =>
            {
                return Task.Run(async () =>
               {
                   var counter = 1;

                   while (true)
                   {
                       lock (lock_obj)
                       {
                           for (int i = 0; i < 100_000; i++)
                           {
                               cd.TryAdd($"{counter}:{i}", new ThreadSafeLong(i));
                               //WriteLine(i);
                           }
                           WriteLine($"Round {counter}");
                       }
                       counter++;
                       await Task.Delay(1_000);
                   }
               });
            };

            Func<Task> writeData = () =>
            {
                return Task.Run(async () =>
              {
                  while (true)
                  {
                      var sw = Stopwatch.StartNew();

                      lock (lock_obj) // to clone the data, and prevent any other data to be added while clone
                      {
                          var cloned = new ConcurrentDictionary<string, ThreadSafeLong>(cd);
                          cd.Clear();
                          WriteLine($"Cloned Count: {cloned.Count}");
                      }

                      sw.Stop();
                      WriteLine($"Elapsed Time: {sw.ElapsedMilliseconds}");

                      await Task.Delay(6_000);
                  }
              });
            };

            await Task.WhenAll(addData(), writeData());

        }
    }

PS:某种程度上可能与这里的问题有关

在这些情况下,我将字典替换为新字典,而不是调用clear:

lock (lock_obj)
{
    var cloned = cd;
    cd = new ConcurrentDictionary<string, ThreadSafeLong>();
}

在这种情况下,其他线程将完成对旧线程的写入或已经使用新线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM