Skip to content
Code quality and reliability Reviewed 2026-09-13

Shared Object Lock

What does this mean ?

A lock must be shared by the operations protecting the same resource. The problem is exposing that lock to unrelated code, for example by locking this, a public Type object, or an interned string. Another caller may acquire the same monitor for a different purpose. See Microsoft's lock guidance.

What can happen ?

Unexpected lock contention can stall work; inconsistent acquisition order can produce a deadlock. These are concurrency and availability risks, not proof that an attacker can exploit every affected method.

Recommendation

Use a dedicated private lock object, consistently covering both reads and writes of protected state. Use a static gate for static shared state. Keep critical sections short and avoid callbacks into unknown code while locked. For C# 13/.NET 9+, a dedicated System.Threading.Lock is also available. await cannot appear inside a lock body; asynchronous coordination needs an appropriate separate design.

Sample Code

Publicly accessible monitor:

public class Counter
{
    private int value;
    public void Increment() { lock (this) { value++; } }
    public int Value { get { lock (this) { return value; } } }
}

Private monitor for the same state:

public class Counter
{
    private readonly object gate = new object();
    private int value;
    public void Increment() { lock (gate) { value++; } }
    public int Value { get { lock (gate) { return value; } } }
}

Regression test: run concurrent increments and assert the exact final count. Hold lock(counter) in an independent task and verify the replacement still makes progress. Include timeout-based failure detection so a concurrency regression cannot hang the test suite.

References