为什么并行访问和更改System.Collections.Generic.Dictionary不会导致异常/崩溃



有人能解释或给我指一些文档吗?这些文档可以解释为什么这个代码没有抛出任何异常:

var d = new Dictionary<object, object>();
System.Threading.Tasks.Parallel.ForEach(new Action[] {
() => {
System.Threading.Tasks.Parallel.For(0, 1024, i => {
d.Add(new object(), new object());
});
},
() => {
System.Threading.Tasks.Parallel.For(0, 1024, i => {
d.TryGetValue(new object(), out _);
});
},
}, a => a());

我试着在我的8核计算机上运行这个程序,希望有什么东西会抛出一个关于无效操作或空引用等的异常,但从来没有。虽然我最终得到了一个元素数量错误的字典,但这怎么不会引发异常和/或崩溃呢?

某些东西不是线程安全的,并不意味着从多个线程使用它会导致它抛出异常。词典<TKey、TValue>类不是线程安全的,并且一次只能由一个线程使用。它可能不包括对哪些线程同时访问它的任何检查,因为这太昂贵了。它只是假设一次只有一个线程访问它。

从多个线程中同时突变一个非线程安全组件既不能保证异常也不能保证崩溃。事实上,它绝对不能保证什么。组件的行为正式成为";"未定义";,这意味着任何事情都有可能发生,包括任何不好的事情都不会发生。但是如果发生了不愉快的事情,那么你就不能去供应商那里填写错误报告,要求修复错误。因为没有bug。供应商可以用以下内容回复您的请求:

尊敬的客户,密封件损坏,保修无效。你选择了进入一片未定义的黑色大森林,那里没有任何规则,现在你只能靠自己了。