7

The SpinLock structure in .Net can be used to manage access to resources from multiple threads. Other than a normal lock it uses a busy waiting, which is faster if the expected wait time is very low (but consumes more resources).

Other threading primitives such as a Monitor and lock(...){} always acquire the lock (or wait forever to acquire it). But the SpinLock.Enter method uses a ref bool parameters to indicate wether or not acquiring the lock failed.

What is the ref bool lockTaken needed and in what cases can Monitor.Enter fail (and thus set lockTaken to false?)

Roy T.
  • 9,429
  • 2
  • 48
  • 70
  • 2
    It helps you make the SpinLock.Exit() call exception-safe. Unlike Monitor, SpinLock itself is prone to throwing exceptions because it is not re-entrant. And the big big dog is [TheadAbortException](http://stackoverflow.com/a/14831590/17034). – Hans Passant Oct 16 '15 at 08:38
  • According to MSDN all methods on `SpinLock` are thread safe, so what do you mean with them not being re-entrant. I understand the issue with `ThreadAbortException` now :). – Roy T. Oct 16 '15 at 08:41
  • 1
    SpinLock can be acquired just once by a thread. Very unlike other .NET synchronization primitives like Monitor and Mutex. If you acquired the lock and then call an innocent looking method that also uses the SpinLock then either your code deadlocks or will throw an exception. It is thread safe but not safe to bugs in your code. – Hans Passant Oct 16 '15 at 08:48

1 Answers1

8

This 'lockTaken' pattern is used in order to be sure about that lock is really taken by thread sync construct. Thing is - Monitor and SpinLock internally exit in finally block and lock is taken in try block.

Now, if thread has entered try block and was aborted before it was taken lock then it shouldn't be released in finally block. That problem is solved via ref bool variable.

Boolean taken = false;
try {
    // An exception (such as ThreadAbortException) could occur here...
    Monitor.Enter(this, ref taken);
}
finally {
    if (taken) Monitor.Exit(this);
}
nikita
  • 2,737
  • 2
  • 20
  • 26