I genuinely had not heard of anyone actually using a spinlock in production code until I started using LMAX Disruptor a few years ago.
I was always told that they were an anti-pattern, and I think that generally that is a pretty good rule of thumb, but I guess like most stuff in CS: there are always exceptions to "good rules of thumb".
I still haven't actually explicitly written a spinlock for anything in production, but Disruptor has shown me that there are cases for it.
One use case I’ve found is for a lock that you don’t need to acquire. For example, you need a lock to read a cache entry, but if you can’t acquire the lock after a few spins, you can just proceed without the cache. For fine-grained locking, a spin lock can have a significantly lower memory overhead than a full futex.
To be really pedantic, it's a spin wait, not a spin lock in disruptor. You are waiting for a sequence, not mutually excluding some resource. Many threads can watch the same volatile at the same time without blocking each other.
If you have an application where your threads are pinned to dedicated cores, and those cores are all isolated from general OS scheduling, then it's the lowest latency means to synchronize arbitrary things between threads
Entering the kernel with a futex wait or wake under contention costs a couple of microseconds, whereas a spinlock will cost you double digit to low triple digit nanos depending on cores/sockets etc
Tell a kernel developer that spin locks aren’t for production code.
Bring a wind turbine with you because the laughing will be quite intense…
I think Linus says it well: https://www.realworldtech.com/forum/?threadid=189711&curpost...
It’s one of the secret ingredients to avoid a Big Kernel Lock™.
> had not heard of anyone actually using a spinlock in production code
Go stdlib sync.Mutex uses spins: https://victoriametrics.com/blog/go-sync-mutex / https://archive.vn/BIb7F
Before we had futexes in the Linux kernel, spinlocks were used to boostrap the implementation of everything else in the user space threading library.
If you have futexes you can try to grab a lock with an atomic operation and if that fails, go wait on the futex via system call, so there is no need to spin. Spinlocks then remain useful as an optimization, because there are situations in which it is cheaper to spin around a bunch of times until the thread on another processor gives up the lock, than to take a trip into the kernel.
You can also spin, but with a scheduler yield in the loop; we don't normally think of that as a spinlock. That's what you fall back on after spinning some number of times and failing to get the lock.
In the Linux kernel, spinlocks are the low level primitive. They are very efficient because unlike user space threading, they are not faced with guesswork about scheduling. They are "surgical".