Search code examples
c#multithreadingspinlock

SpinLock doesn't really do busy-loop waiting?


I have the following code

class Program
    {
        static SpinLock sl = new SpinLock();

        public static void Foo(object arg)
        {
            bool r = false;
            sl.Enter(ref r);
        }
        public static void Main(string[] args)
        {
            bool r = false;
            sl.Enter(ref r);
            ThreadPool.QueueUserWorkItem(Foo);
            Thread.Sleep(5000);
            sl.Exit();
            Thread.Sleep(5000);
        }
    }

When I execute it, I see ~0% of the CPU load throughout the whole program run. I was expecting to see some CPU burn due to spinning inside the sl.Enter() call, but this is not the case.

According to SpinLock source, it uses SpinWait under the hood, which in turn actually calls Thread.Sleep(1) at some point.

Does that mean that both SpinLock and SpinWait aren't really "spinners", but instead still resort to the OS scheduler to yield some CPU shares?

EDIT

The question can be reformulated in the following way:

Using busy-looping ensures that the time between one thread releasing a lock and another thread acquiring it is minimal. Can I rely on SpinLock/SpinWait in this regard? From what I can tell, the answer is no, because it does Sleep for at least 1 microsecond, and the lock might be freed somewhere during this time.


Solution

  • Regarding your edited question, yes busy spinning will give you the lowest latency of communication between the threads but you will pay for it by burning CPU time.

    On the other hand you can use SpinWait which is less aggressive or you can code something in between such as this.

    It comes down to a trade-off on how much you value latency and how many cores you have to spare.