MSDN文档是这么说的

public class SomeObject
{
  public void SomeOperation()
  {
    lock(this)
    {
      //Access instance variables
    }
  }
}

是“如果实例可以公开访问,则会出现问题”。我想知道为什么?这是因为锁持有的时间比需要的时间长吗?还是有更阴险的原因?


当前回答

想象一下,你的办公室有一位技术娴熟的秘书,这是部门的共享资源。偶尔,你会因为有任务而冲向他们,只希望你的另一个同事还没有认领他们。通常你只需要等很短的一段时间。

因为关心就是分享,你的经理决定顾客也可以直接使用秘书。但这有一个副作用:当您为该客户工作时,客户甚至可能会认领它们,并且您还需要他们执行部分任务。死锁发生,因为声明不再是层次结构。如果从一开始就不允许客户索赔,这完全可以避免。

lock(this) is bad as we've seen. An outside object might lock on the object and since you don't control who's using the class, anyone can lock on it... Which is the exact example as described above. Again, the solution is to limit exposure of the object. However, if you have a private, protected or internal class you could already control who is locking on your object, because you're sure that you've written your code yourself. So the message here is: don't expose it as public. Also, ensuring that a lock is used in similar scenario's avoids deadlocks.

与此完全相反的是锁定整个应用领域共享的资源——这是最坏的情况。这就像把你的秘书放在外面,让外面的人去认领一样。结果是彻底的混乱——或者就源代码而言:这是一个坏主意;把它扔掉,重新开始。我们怎么做呢?

正如这里大多数人指出的那样,类型在应用领域是共享的。但是我们可以使用更好的东西:字符串。原因是字符串被池化了。换句话说,如果你有两个字符串在一个应用域中有相同的内容,它们有可能有完全相同的指针。由于指针被用作锁键,基本上你得到的是“为未定义的行为做好准备”的同义词。

类似地,你不应该锁定WCF对象HttpContext。目前,线程。当前,单例(一般)等。避免这一切的最简单方法是什么?private [static] object myLock = new object();

其他回答

如果可以公开访问实例,就会出现问题,因为可能有其他请求正在使用相同的对象实例。最好使用私有/静态变量。

看看MSDN主题线程同步(c#编程指南)

Generally, it is best to avoid locking on a public type, or on object instances beyond the control of your application. For example, lock(this) can be problematic if the instance can be accessed publicly, because code beyond your control may lock on the object as well. This could create deadlock situations where two or more threads wait for the release of the same object. Locking on a public data type, as opposed to an object, can cause problems for the same reason. Locking on literal strings is especially risky because literal strings are interned by the common language runtime (CLR). This means that there is one instance of any given string literal for the entire program, the exact same object represents the literal in all running application domains, on all threads. As a result, a lock placed on a string with the same contents anywhere in the application process locks all instances of that string in the application. As a result, it is best to lock a private or protected member that is not interned. Some classes provide members specifically for locking. The Array type, for example, provides SyncRoot. Many collection types provide a SyncRoot member as well.

...同样的论点也适用于这个结构:

lock(typeof(SomeObject))

这里有一个更简单的例子(来自这里的问题34),为什么锁(this)是不好的,并且当你的类的消费者也试图锁定对象时可能会导致死锁。 下面,三个线程中只有一个线程可以继续,其他两个线程处于死锁状态。

class SomeClass { public void SomeMethod(int id) { **lock(this)** { while(true) { Console.WriteLine("SomeClass.SomeMethod #" + id); } } } } class Program { static void Main(string[] args) { SomeClass o = new SomeClass(); lock(o) { for (int threadId = 0; threadId < 3; threadId++) { Thread t = new Thread(() => { o.SomeMethod(threadId); }); t.Start(); } Console.WriteLine(); }

为了解决这个问题,这家伙使用了Thread。TryMonitor(带超时)而不是lock:

班长。TryEnter(temp, millisecondsTimeout, ref lockWasTaken); 如果(lockWasTaken) { doAction (); } 其他的 { 抛出新的异常(" cannot get lock"); }

https://blogs.appbeat.io/post/c-how-to-lock-without-deadlocks

我知道这是一个旧线程,但因为人们仍然可以查找并依赖它,因此有必要指出lock(typeof(SomeObject))明显比lock(this)差。话虽如此;对Alan指出lock(typeof(SomeObject))是不好的做法表示由衷的赞扬。

System的一个实例。Type是最通用的粗粒度对象之一。至少是System的一个实例。Type对于AppDomain是全局的,. net可以在一个AppDomain中运行多个程序。这意味着,如果两个完全不同的应用程序都试图在System.Type的同一个全局实例上获得同步锁,那么它们可能会对彼此造成潜在的干扰,甚至产生死锁。

因此,lock(这)并不是特别健壮的形式,可能会导致问题,并且由于所引用的所有原因应该总是令人惊讶。然而,像log4net这样广泛使用、相对受人尊敬且明显稳定的代码广泛使用锁(此)模式,尽管我个人更希望看到这种模式发生变化。

但是lock(typeof(SomeObject))打开了一个全新的增强的蠕虫容器。

不管怎样。