Skip to content

Spinlock

A spinlock is a concurrency control mechanism used in multithreading to achieve [[Atomicity|atomicity]] and manage access to shared resources, such as the reference count in a buffer.^[600-developer-big-data-netty-netty-rotate.md]

Mechanism

The core implementation of a spinlock involves an infinite loop, often implemented using for (;;) or while (true), in which a thread continuously attempts to update a shared state.^[600-developer-big-data-netty-netty-rotate.md]

Instead of yielding or blocking the thread upon encountering contention, the thread "spins" in place.^[600-developer-big-data-netty-netty-rotate.md] It repeatedly checks if a critical condition—such as the availability of a lock or a specific value change—is met, effectively waiting for the resource to become free without leaving the execution context.^[600-developer-big-data-netty-netty-rotate.md]

Comparison with Blocking

The primary characteristic of a spinlock is its busy-wait nature.^[600-developer-big-data-netty-netty-rotate.md] Unlike traditional locking mechanisms that might involve putting a thread to sleep (blocking) and incurring the overhead of a context switch, a spinlock keeps the thread active in a loop, waiting for a specific condition to resolve.^[600-developer-big-data-netty-netty-rotate.md]

Example Implementation

In the context of Netty, spinlock logic is evident within the retain0 and release0 methods of AbstractReferenceCountedByteBuf.^[600-developer-big-data-netty-netty-rotate.md]

private [ByteBuf](<./bytebuf.md>) retain0(int increment) {
    for (;;) {
        int refCnt = this.refCnt;
        final int nextCnt = refCnt + increment;

        // Ensure we not resurrect (which means the refCnt was 0) and also that we encountered an overflow.
        if (nextCnt <= increment) {
            throw new IllegalReferenceCountException(refCnt, increment);
        }
        if (refCntUpdater.compareAndSet(this, refCnt, nextCnt)) {
            break;
        }
    }
    return this;
}

In this example, the code uses an infinite loop to perform a Compare-and-swap (CAS) operation via compareAndSet.^[600-developer-big-data-netty-netty-rotate.md] The loop continues to spin until the atomic update of the reference counter (refCnt) is successful.^[600-developer-big-data-netty-netty-rotate.md]

Sources

^[600-developer-big-data-netty-netty-rotate.md]