SpinLock Readonly

ID

csharp.spinlock_readonly

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

concurrency, reliability

Description

Reports fields whose type is SpinLock and which are declared readonly. Because SpinLock is a mutable value type, the readonly modifier forces every access to return a defensive copy and the lock no longer synchronises anything.

Rationale

SpinLock is implemented as a mutable struct. The lock state is stored inside the struct value itself. When the field that holds the SpinLock is readonly, the compiler copies the struct on every member access, so Enter is called on one copy and Exit on another. The threads believe they are synchronising but in reality each one sees its own unrelated lock state and the lock is silently broken.

using System.Threading;

public class Worker
{
    private readonly SpinLock badSpin = new SpinLock();   // FLAW — each access copies
    private SpinLock goodSpin = new SpinLock();           // OK — mutable backing field

    public void DoWork()
    {
        bool taken = false;
        goodSpin.Enter(ref taken);
        try { /* ... */ }
        finally { if (taken) goodSpin.Exit(); }
    }
}

Remediation

Remove the readonly modifier from SpinLock fields. If immutability of the containing object is important, prefer the reference-type lock statement or SemaphoreSlim, which can safely be held in a readonly field.