Use of SpinLock for ThreadLocking

Yesterday, I have posted one tip which discusses how you could use ReaderWriterLock to implement shared locking on items that does require concurrent access. Today I will use SpinLock to do the same.

SpinLock like Monitor spins a number of CPU cycles when it tries to acquire a lock. Monitor on the other hand Spins some CPU Cycle at first but also invokes a True wait after a certain time if lock cannot be acquired. In case of Multicore machines, the Wait timer for Monitor is actually left very short and in certain scenarios it is better to use SpinLock instead of Montor of Interlocked. But it is recommended to check the performance beforehand using the SpinLock in profiler.

<br />
static SpinLock _spinlock = new SpinLock();<br />
public static List<int> Repository = new List<int>();<br />
public static long Sum()<br />
{</p>
<p>    bool lockTaken = false;<br />
    _spinlock.Enter(ref lockTaken);<br />
    long counter = 0;<br />
    try<br />
    {<br />
        for (int i = 0; i < Repository.Count; i++)<br />
            Interlocked.Add(ref counter, Repository[i]);<br />
    }<br />
    finally<br />
    {<br />
        if(lockTaken)<br />
            _spinlock.Exit();<br />
    }<br />
    return counter;<br />
}</p>
<p>public static void AddToRepository(int nos)<br />
{<br />
    bool lockTaken = false;<br />
    if (_spinlock.IsHeld)<br />
        return;</p>
<p>    _spinlock.TryEnter(1000, ref lockTaken);</p>
<p>    try<br />
    {<br />
        for (int i = 0; i < nos; i++)<br />
            Repository.Add(i);<br />
    }<br />
    catch { }<br />
    if (lockTaken)<br />
        _spinlock.Exit();<br />
}

The SpinLock has an Enter and Exit to acquire and release the lock. It requires a Boolean field to be passed to it which ensures whether the lock is actually acquired or not. The TryEnter is used to specify the Timeout seed for the lock.

As I have already told you, SpinLock will yield few timeslices when it hasn’t acquired the lock, this will ensure that the Garbage collector makes progression on the block it tries to acquire the lock. Another important point is that SpinLock is a structure, and if more than one thread require to check the lock, it should be passed by reference.

SpinLock also allows you to check whether the Lock is held by any thread using IsHeld property or even you can check whether the current thread holds the Lock using IsHeldByCurrentThread property. If more than one thread Tries to acquire the locked resource, the SpinLock generates LockRecursionException, and hence SpinLock is not reenterant.

I hope this post will help you

Thanks for reading.

Abhishek Sur

Abhishek Sur is a Microsoft MVP since year 2011. He is an architect in the .NET platform. He has profound theoretical insight and years of hands on experience in different .NET products and languages. He leads the Microsoft User Group in Kolkata named KolkataGeeks, and regularly organizes events and seminars in various places for spreading .NET awareness. He is associated with the Microsoft Insider list on WPF and C#, and is in constant touch with product group teams. He blogs at http://www.abhisheksur.com His Book : Visual Studio 2012 and .NET 4.5 Expert Development Cookbook. Follow Abhishek at Twitter : @abhi2434