If a lock is known to be held or acquired, and then released within a method, then it must be released along all execution paths of that
method.
Failing to do so will expose the conditional locking logic to the method’s callers and hence be deadlock-prone.
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