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.