为什么并行访问和改变 System.Collections.Generic.Dictionary 不会导致 exceptions/crashes?
Why does accessing and mutating a System.Collections.Generic.Dictionary in parallel not result in exceptions/crashes?
有人可以解释或指出一些文档可以向我解释为什么这段代码不会抛出任何异常:
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 核计算机上试过 运行 这个,期望某些东西会抛出关于无效操作或空引用等的异常,但它从来没有。虽然我最终得到了一个元素数量错误的字典,但这怎么不会抛出异常 and/or 崩溃?
仅仅因为某些东西不是线程安全的并不意味着从多个线程使用它会导致它抛出异常。 Dictionary class 不是线程安全的,一次只能由一个线程使用。它可能不包括对同时访问它的线程的任何检查,因为这太昂贵了。它只是假设一次只有一个线程访问它。
同时从多个线程改变一个非线程安全的组件既不会保证异常也不会崩溃。实际上,它绝对不能保证任何事情。组件的行为正式变为“未定义”,这意味着任何事情都可能发生,包括根本不会发生任何不良事件。但是如果发生了一些不愉快的事情,那么你就不能去供应商那里填写错误报告,要求修复错误。因为没有bug。供应商可以使用以下内容回复您的请求:
Dear customer, the seal is broken, the warranty is void. You've chosen to enter the big black forest of undefined territory, where no rules apply, and now you are on your own.
有人可以解释或指出一些文档可以向我解释为什么这段代码不会抛出任何异常:
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 核计算机上试过 运行 这个,期望某些东西会抛出关于无效操作或空引用等的异常,但它从来没有。虽然我最终得到了一个元素数量错误的字典,但这怎么不会抛出异常 and/or 崩溃?
仅仅因为某些东西不是线程安全的并不意味着从多个线程使用它会导致它抛出异常。 Dictionary
同时从多个线程改变一个非线程安全的组件既不会保证异常也不会崩溃。实际上,它绝对不能保证任何事情。组件的行为正式变为“未定义”,这意味着任何事情都可能发生,包括根本不会发生任何不良事件。但是如果发生了一些不愉快的事情,那么你就不能去供应商那里填写错误报告,要求修复错误。因为没有bug。供应商可以使用以下内容回复您的请求:
Dear customer, the seal is broken, the warranty is void. You've chosen to enter the big black forest of undefined territory, where no rules apply, and now you are on your own.