c# – .Net中的Dictionary可能会在并行阅读和写入时造成死锁吗?

c# – .Net中的Dictionary可能会在并行阅读和写入时造成死锁吗?,第1张

概述我正在和TPL一起玩,并尝试通过并行阅读和写作到同一个字典,找出我能做出多大的麻烦. 所以我有这个代码: private static void HowCouldARegularDicionaryDeadLock() { for (var i = 0; i < 20000; i++) { TryToReproduceProblem() 我正在和TPL一起玩,并尝试通过并行阅读和写作到同一个字典,找出我能做出多大的麻烦.

所以我有这个代码:

private static voID HowCouldARegularDicionaryDeadLock()    {        for (var i = 0; i < 20000; i++)        {            TryToReproduceProblem();        }    }    private static voID TryToReproduceProblem()    {        try        {            var dictionary = new Dictionary<int,int>();            Enumerable.Range(0,1000000)                .ToList()                .AsParallel()                .ForAll(n =>                {                    if (!dictionary.ContainsKey(n))                    {                        dictionary[n] = n; //write                    }                    var readValue = dictionary[n]; //read                });        }        catch (AggregateException e)        {            e.Flatten()                .InnerExceptions.ToList()                .ForEach(i => Console.Writeline(i.Message));        }    }

这真的很混乱,有很多异常抛出,主要是关键不存在,有几个关于索引的数组的界限.

但运行该应用程序一段时间后,它挂起,cpu百分比保持在25%,机器有8个内核.
所以我假设有2个线程以满容量运行.

然后我点了点跟踪,得到这个:

它匹配我的猜测,两个线程运行在100%.

两者都运行Dictionary的FindEntry方法.

然后我再次运行应用程序,用dottrace,这个时候结果略有不同:

这一次,一个线程正在运行FindEntry,另一个插入.

我的第一个直觉是它被锁死了,但后来我以为这不可能,只有一个共享资源,而且它没有被锁定.

那么应该如何解释呢?

ps:我不是想解决这个问题,它可以通过使用ConcurrentDictionary或者并行聚合来修复.我只是在寻找一个合理的解释.

解决方法 看起来像一个竞争条件(不是一个僵局) – 正如你所说,这导致内部混乱的状态.

字典不是线程安全的,因此从单独的线程(即使只有少数几个)并发读取和写入同一容器是不安全的.

一旦比赛条件受到打击,将会发生什么变化,在这种情况下,似乎是某种无限循环.

通常,一旦需要写入访问,就需要某种形式的同步.

总结

以上是内存溢出为你收集整理的c# – .Net中的Dictionary可能会在并行阅读和写入时造成死锁吗?全部内容,希望文章能够帮你解决c# – .Net中的Dictionary可能会在并行阅读和写入时造成死锁吗?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1259747.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存