If a lock is held or acquired and then released within a method, it should be released along all execution paths.

Failing to do so could make an application deadlock-prone because there is a risk of the lock not being released.

The types tracked by the rule are: Monitor, Mutex, ReaderWriterLock, ReaderWriterLockSlim and SpinLock from the System.Threading namespace.

Noncompliant Code Example

class MyClass
{
  private object obj = new object();

  public void DoSomethingWithMonitor()
  {
    Monitor.Enter(obj); // Noncompliant
    if (IsInitialized())
    {
      // ...
      Monitor.Exit(obj);
    }
  }

  private ReaderWriterLockSlim lockObj = new ReaderWriterLockSlim();

  public void DoSomethingWithReaderWriteLockSlim()
  {
    lockObj.EnterReadLock(); // Noncompliant
    if (IsInitialized())
    {
      // ...
      lockObj.ExitReadLock();
    }
  }
}

Compliant Solution

class MyClass
{
  private object obj = new object();

  public void DoSomethingWithMonitor()
  {
    lock(obj) // lock() {...} is easier to use than explicit Monitor calls
    {
      if (IsInitialized())
      {
      }
    }
  }

  private ReaderWriterLockSlim lockObj = new ReaderWriterLockSlim();

  public void DoSomethingWithReaderWriteLockSlim()
  {
    lockObj.EnterReadLock();
    try
    {
      if (IsInitialized())
      {
      }
    }
    finally
    {
      lockObj.ExitReadLock();
    }
  }
}

See