joydip_kanjilal
Contributor

My two cents on SpinLock in .Net

opinion
Jul 12, 20164 mins
Software Development

SpinLock handles "busy wait" in scenarios where you have frequent contention but with reasonably short waiting times by avoiding context switches and improving performance

Imagine a situation in which a thread is trying to acquire access to a shared resource but the resource is already locked, so the thread has to wait until the lock is released. Here’s where thread synchronization comes into play. Thread synchronization is used to prevent multiple threads from accessing a shared resource concurrently. The Microsoft .Net Framework provides support for a range of synchronization primitives that can be used for controlling thread behavior and avoiding race conditions. Mutex and Spinlock are two popular synchronization mechanisms used to synchronize access to a shared resource.

A SpinLock is an alternative to blocking synchronization. SpinLock (also known as “Busy Waiting”) is a mechanism that can be used to make a thread trying to acquire a lock wait in a loop till it can get access to the resource. Note that SpinLock can perform faster compared to Mutex since context switching is reduced. However, you should use SpinLocks only if the critical section is supposed to perform a minimal amount of work, i.e., the SpinLock is held for a very short period of time. SpinLocks are usually preferred in symmetric multiprocessor systems to constantly poll for availability of a resource in lieu of context switches.

What is SpinLock and why is it needed?

SpinLock performs busy waiting and can offer better performance when used in multi-core systems especially when it is cheap to wait in a loop and pool a resource rather than block on it. This is particularly helpful when the lock hold times are of a short duration. In other words, you can take advantage of SpinLock in multi-core systems to reduce the overhead involved in context switching if the time to be spent inside the critical section is small. A critical section may be defined as a data structure or a resource that is shared by multiple threads but one and only one thread can have access to it at any given point of time.

It should be noted that holding SpinLock for longer duration would simply be a waste of the system’s resources and detrimental to the application’s performance. In essence, if you expect the blocking to be of a significant duration, SpinLock should never be used — use SpinLock only when the lock hold-times of a reasonably small duration.

SpinLock are typically used when working with interrupts to perform busy waiting inside a loop till the resource is made available. SpinLock don’t cause the thread to be preempted, rather, it continues to spin till lock on the resource is released.

Programming SpinLock in .Net

Note that a SpinLock is defined as a struct in .Net, i.e., it is defined as a value type for performance reasons. Hence, if you are passing around a SpinLock instance, you should pass it by reference and not by value. In this section we will explore how we can program SpinLock in .Net. To implement SpinLock in .Net, you would need to take advantage of the SpinLock class available in the System.Threading namespace.

The following code listing shows how you can use SpinLock in .Net.

SpinLock spinLock = new SpinLock (true);

bool isLocked = false;

try

{

spinLock.Enter (ref isLocked);

// Write your usual code here

}

finally

{

if (isLocked)

   spinLock.Exit();

}

SpinWait

Note that like SpinLock, SpinWait is also a struct and not a class. Similar to SpinLock, you can use SpinWait to write lock free synchronization code that can “spin” rather than block. SpinWait can be used to reduce resource consumption by performing CPU intensive spinning for 10 iterations post which it will yield the control by calling Thread.Yield and Thread.Sleep. In other words, SpinWait can be used to limit CPU-intensive spinning to a fixed number of iterations. The MSDN states: “System.Threading.SpinWait is a lightweight synchronization type that you can use in low-level scenarios to avoid the expensive context switches and kernel transitions that are required for kernel events.”

To use SpinWait in your code, you can either leverage the SpinUntil() static method of the SpinWait struct, or, take advantage of its SpinOnce() non-static method. The following code snippet illustrates how SpinWait can be used.

SpinWait spinWait = new SpinWait();

bool shouldSpin;

while (!shouldSpin)

{

   Thread.MemoryBarrier(); spinWait.SpinOnce();

}

joydip_kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author