为什么“锁定(typeof(MyType))”有问题?

时间:2009-10-21 19:19:51

标签: c# multithreading locking

MSDN对C#中的 lock 关键字发出以下警告:

  

一般情况下,避免锁定公众   类型或代码之外的实例   控制。常见的构造锁定   (this),lock(typeof(MyType))和   锁(“myLock”)违反此规定   准则:

* lock (this) is a problem if the instance can be accessed publicly.
* lock (typeof (MyType)) is a problem if MyType is publicly accessible.

但它没有给出任何可靠的推理。锁(this)解释为here on SO。我对lock(typeof(MyType))案件感兴趣。什么危险呢?

谢谢。

6 个答案:

答案 0 :(得分:59)

这是危险的,因为任何东西都可以锁定,因此很难或不可能防止死锁情况。

曾经有过一篇关于此的文章(“请勿锁定类型对象!”一篇GUI博士文章)以及Rico Mariani的一些评论。显然这篇文章不再直接可用,但有“镜子”浮动,包括在http://bytes.com/topic/c-sharp/answers/249277-dont-lock-type-objects

以下是摘录:

  

这里的基本问题是您不拥有类型对象,并且您不知道还有谁可以访问它。一般来说,依靠锁定一个你没有创建的对象并且不知道还有谁可能访问它是一个非常糟糕的主意。这样做会引发僵局。最安全的方法是仅锁定私有对象。

     

但等等;它甚至比这更糟糕。事实证明,类型对象有时在.NET运行时的当前版本中跨应用程序域(但不跨进程)共享。 (这通常是可以的,因为它们是不可变的。)这意味着即使在不同的应用程序域(但在同一个进程中)运行的另一个应用程序也可能通过锁定要锁定的类型对象来使应用程序死锁永远不会释放它。并且很容易访问该类型对象,因为该对象具有名称 - 该类型的完全限定名称!请记住,锁定/ SyncLock阻塞(这是挂起的礼貌用语),直到它可以获得锁定。依赖于另一个程序或组件可以锁定并导致您死锁的锁定显然非常糟糕。

答案 1 :(得分:27)

lock(this)一样的问题 - 您正在锁定其他代码可以访问的引用,因此它也可以锁定它。

如果你有两个不相关的代码锁定在同一个引用而没有打算相互排斥,那么在最好的情况下,由于缺乏并发性,你可能会失去一点性能 - 以及在最坏的情况下,你可能会引入僵局。

答案 2 :(得分:2)

因为typeof (MyType)(类型为Type的对象)的结果可以被广泛访问,而其他线程可以锁定同一个对象,并且无限期地保持该锁定。然后,MyType的内部逻辑有效地放弃了对其同步逻辑的重要控制。如果是这样的话,这可能不是一个实际问题,但是防御性/怀疑性的编码应该是你的操作手法

答案 3 :(得分:0)

因为锁的目标只是建立一个存储锁布尔值的位置(我是否锁定)以供其他线程查看....

锁定目标实际上被锁定的常见误解是错误的...什么是“锁定”是......什么都没有,除非在以不安全的方式访问某些共享内存的方法中,你编写代码来查看这个锁,直到它被释放后才继续...使用Type对象,因为锁定目标是错误的,因为代码片段在整个解决方案进程空间的任何地方都可以访问该类型对象并更改存储锁布尔值的同步块。创建本地作用域对象可以更好地确保只有那些可以访问或搞乱“有风险”共享内存的线程和方法也可以访问和/或修改锁。

答案 4 :(得分:0)

还有主题"托管线程最佳实践"下的文档。 https://msdn.microsoft.com/en-us/library/1c9txz50(v=vs.110).aspx

它说;

  

不要将类型用作锁定对象。也就是说,避免代码如   在Visual Basic中的C#或SyncLock(GetType(X))中锁定(typeof(X)),或者   使用Monitor.Enter与Type对象。 对于给定的类型,有   每个应用程序域只有一个System.Type实例。如果是这种类型   你公开锁定,你自己以外的代码可以锁定   在它上面,导致死锁。有关其他问题,请参阅Reliability   Best Practices

     

锁定实例时请小心,例如在C#中使用锁定(this)   Visual Basic中的SyncLock(Me)。如果您的应用程序中有其他代码   在类型外部,锁定对象,死锁可以   的发生

答案 5 :(得分:0)

这不是一个问题"如果遵循这种修改并行形式的建议:

  

通常,请避免锁定公共类型或未创建或定义的实例 。如果您未创建实例或声明类型,则常见构造chrome.app.window.createlock (this)违反此准则

但是,由于以上情况无法保证&#39;对于所有遇到的代码中的公共类型或可访问实例, MSDN和其他来源认为防御性编程应避免针对单个潜在的难以检测的运行时(死锁)问题< / strong>即可。鉴于大多数程序员对规则不是很好或不勤奋,这是一个很好的建议。

..并且在野外遇到此类错误的人会更加坚定地认为允许通过强制执行指导原则再次发生此特定问题。 (带有Threaded AWT UI模型的Java 1.0 / 1.1特别成问题。)

lock (typeof (MyType))的情况非常特殊,因为字符串实习可以避免 ,因为人们通常不会知道&#34;如果他们违反了上述建议..