Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么是;锁(typeof(MyType))”;有问题吗?_C#_Multithreading_Locking - Fatal编程技术网

C# 为什么是;锁(typeof(MyType))”;有问题吗?

C# 为什么是;锁(typeof(MyType))”;有问题吗?,c#,multithreading,locking,C#,Multithreading,Locking,MSDN对C#中的lock关键字发出以下警告: 一般情况下,避免锁定公共区域 类型,或超出代码范围的实例 控制通用构造锁 (this)、锁(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.

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

一般情况下,避免锁定公共区域 类型,或超出代码范围的实例 控制通用构造锁 (this)、锁(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.
但它没有给出可靠的理由。说明了锁(这个)。我对锁(MyType)盒感兴趣。它有什么危险


谢谢。

这与
锁定(此)
的问题相同-您锁定了其他代码可以访问的引用,因此它也可能锁定


如果在同一引用上有两段不相关的代码锁定,而不打算相互排除,然后,在最好的情况下,由于缺乏并发性,您可能会损失一些性能,在最坏的情况下,您可能会引入死锁。

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

过去有一篇关于这个的文章(“不要锁定类型对象!”一篇Dr.GUI文章),里科·马里亚尼对此发表了一些评论。显然,这篇文章已不再直接提供,但到处都是“镜子”,包括at

这里有一段摘录:

这里的基本问题是您不拥有类型对象,并且您不知道还有谁可以访问它。一般来说,依赖于锁定一个你没有创建的对象,并且不知道还有谁在访问,这是一个非常糟糕的想法。这样做会导致僵局。最安全的方法是只锁定私有对象

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


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

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


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

在“托管线程最佳实践”主题下的文档中也有说明。

它说,

不要将类型用作锁定对象。也就是说,避免使用以下代码 C#中的lock(typeof(X))或visualbasic中的SyncLock(GetType(X))或 使用监视器。使用类型对象输入对于给定类型,有 每个应用程序域只有一个System.Type实例。如果类型 如果你的密码是公开的,那么除了你自己的密码之外,其他的密码都可以被锁定 它会导致死锁。有关其他问题,请参阅

锁定实例时要小心,例如C#中的锁定(this);或 Visual Basic中的同步锁(Me)。如果应用程序中有其他代码, 在类型外部,对对象进行锁定,死锁可以 发生

若遵循这种修改后的平行建议形式,这就不会是“问题”:

通常,避免锁定公共类型或未创建或定义的实例。如果您没有创建实例或声明类型,则常见构造
lock(this)
lock(typeof(MyType))
违反了此准则

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

…如果有人在野外遇到这种错误,他会更加坚决地不让这种特定问题再次发生,因为他会强制执行规定的指导方针。(带有线程化AWT UI模型的Java 1.0/1.1尤其有问题。)


lock(“mylock”)
的情况非常特殊,因为它应该避免使用字符串,因为人们通常无法“知道”它们是否违反了上述建议。

Hmm。。。我想我对lock关键字有更大的误解。从你的描述来看,如果我的程序中完全不相关的部分有两个锁,它们锁定在同一类型上。如果一个线程占用一个锁,则没有线程