锁内锁的理由是什么?

Yeo*_*nho 5 c# multithreading locking

我正在查看书中的示例代码,并遇到了以下代码(简化).在代码中,当Subscribe(T subscriber)调用时,线程进入锁定部分.然后,当锁内部的代码调用AddToSubscribers(T subscriber)方法时,该方法有另一个锁.为什么这第二个锁是必要的?

public abstract class SubscriptionManager<T> where T : class 
{
   private static List<T> subscribers;
   private static void AddToSubscribers(T subscriber)
   {
      lock (typeof(SubscriptionManager<T>))
      {
         if (subscribers.Contains(subscriber))
            return;
         subscribers.Add(subscriber);
      }
   }

   public void Subscribe(T subscriber)
   {
      lock (typeof(SubscriptionManager<T>))
      {
         AddToSubscribers(subscriber);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 9

在这种情况下,它不是; 但是,因为锁是可重入的,可以用于确保任何其他调用者AddToSubscribers观察锁.实际上,出于这个原因,我会说"将其从中删除,Subscribe然后让AddToSubscribers锁定".

然而!对a的锁Type是非常危险的.一个字段会更安全:

// assuming static is correct
private static readonly object syncLock = new object();
Run Code Online (Sandbox Code Playgroud)

lock(syncLock).根据subscribers分配的时间,您可能也会逃避lock(subscribers)(并且没有额外的字段).

我还应该注意,将实例方法添加到静态状态是非常不寻常的.IMO Subscribe应该是一种static方法,因为它与当前实例无关.

  • @Joe不,那是不对的; 泛型类型中的静态字段是per-generic-type-parameter-permutation,因此在这种情况下为per-`T`. (5认同)
  • @Marc你是对的,我错了,今天学到了东西,+ 1 (2认同)