我面临着一个令人不安的情况。
我有一个包含空键条目的词典......
这在我的iis应用程序中不时发生,然后在此字典(100%cpu,无限循环)上执行查找时冻结:
FindEntry方法的来源(未编译或reference sources)非常清楚:
1)词典中没有空键
2)鉴于我的字典私有字段,无限循环非常明显:
任何想法发生在我身上?
ps:我没有像ryujit或custom .net build那样安装任何有趣的东西。 只是在.Net 4.5下运行的常规iisexpress
修改
根据要求(我应该已经准确):我也没有对这本词典做任何有趣的事情。 只有一种用法:
if (!readers.TryGetValue(type, out ret))
readers[type] = ret = GetReaderOfTMethod.MakeGenericMethod(type).Invoke(this,null);
答案 0 :(得分:3)
如果这个字典不限于一个线程(在一个方法中创建并在那里使用,但是静态存储),那么我希望这会发生。
Dictionary
与任何其他代码一样,编写了关于之前可能发生的事情的假设。这些假设不考虑同时呼叫,例如假设如果调整字典大小,调整大小不会再次发生,直到完成调整大小,一次只能进行一次尝试来设置给定值,依此类推。
不要防范这种情况,并且两个调用可以将字典置于其编码器未考虑的状态,然后可能发生无意义的事情,就像有一个空键,即使空键不是'允许。
如果这种同时使用不常见(而且似乎不会),那么用锁来保护每次访问:
lock(lockObj)
if (!readers.TryGetValue(type, out ret))
readers[type] = ret = GetReaderOfTMethod.MakeGenericMethod(type).Invoke(this,null);
其中lockObj
是与readers
在同一范围内的对象,用于锁定对它的所有访问。 (可能readers
在这里可以很好地作为锁定对象本身,但是当这是一个好主意本身就是另一个主题时。)
如果reader
还有其他用途,也应使用相同的锁定对象锁定它们。
如果这种同时使用是常见的,那么设计为容忍此类用途的并发字典会更好(框架中ConcurrentDictionary
,或者我的ThreadsafeDictionary
都可以工作)。这些通常效率较低,但在一定水平的并发使用之上效率更高。