为什么在下面的代码中使用lock是一种不好的做法,我假设这是一个基于this SO question here答案的不良做法
private void DoSomethingUseLess()
{
List<IProduct> otherProductList = new List<IProduct>();
Parallel.ForEach(myOriginalProductList, product =>
{
//Some code here removed for brevity
//Some more code here :)
lock (otherProductList)
{
otherProductList.Add((IProduct)product.Clone());
}
});
}
答案超过there提到这是不好的做法,但他们没有说明原因
Note: 请忽略代码的用处,这只是为了示例目的,我知道它根本没用
2 回答
从C#语言参考here:
在你的情况下,我会阅读上面的指导,建议锁定你将要修改的集合是不好的做法 . 例如,如果您编写此代码:
......那么你的锁将毫无 Value . 由于这些原因,建议使用专用的
object
变量进行锁定 .请注意,这并不意味着如果您使用您发布的代码,您的应用程序将会中断 . "Best practices"通常被定义为提供技术上更具弹性的易于重复的模式 . 也就是说,如果你遵循最佳实践并拥有一个专门的"lock object,",你几乎不可能写出破碎的基于
lock
的代码;如果你不被一个容易避免的问题所困扰 .此外(更一般地说),使用最佳实践编写的代码通常更容易修改,因为您可以避免意外的副作用 .
确实可能不是一个好主意,因为如果其他人使用相同的对象引用来执行
lock
,则可能会出现死锁 . If there is a chance your locked object is accessible outside your own code ,然后其他人可能会破坏您的代码 .想象一下基于您的代码的以下示例:
现在您编译库,将其发送给客户,此客户在其代码中写入:
然后,对于您的客户来说,可能存在一个难以调试的难以解决的死锁,两个用过的线程中的每一个都在等待
otherProductList
实例不再被锁定 .我同意,这种情况不太可能发生,但它说明了 if your locked reference is visible in a piece of code you do not own, by any possible way, then there's a possibility for the final code to be broken .