Why is this an issue?
A shared resource refers to a resource or data that can be accessed or modified by multiple threads or concurrent parts of a program. It could be any piece of data, object, file,
database connection, or system resource that needs to be accessed or manipulated by multiple parts of a program concurrently.
Shared resources should not be used for locking as it increases the chance of
deadlocks. Any other thread could acquire (or attempt to acquire) the same lock while doing some
operation, without knowing that the resource is meant to be used for locking purposes.
One case of this is strings, which are interned by the runtime. This means
that each string instance is immutable and stored, and then is reused everywhere it is referenced.
Instead, a dedicated private object
instance should be used for each shared resource. Making the lock-specific object
private
guarantees that the access to it is as minimal as possible, in order to avoid deadlocks or lock contention.
The following objects are considered as shared resources:
- a reference to this: if the instance is publicly
accessibly, the lock might be shared
- a Type object: if the type class is publicly accessibly, the lock might
be shared
- a string literal or instance: if any other part of the
program uses the same string, the lock is shared because of interning
How to fix it
Code examples
Noncompliant code example
void MyLockingMethod()
{
lock (this) // Noncompliant
{
// ...
}
}
Compliant solution
private readonly object lockObj = new object();
void MyLockingMethod()
{
lock (lockObj)
{
// ...
}
}
Resources
Documentation