2012-08-29

SpinLock SynchronizationLockException - The calling thread does not hold the lock

Here is the code from a console app.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication48
{
class Program
{
static readonly SpinLock SpinLock = new SpinLock();
static void Main(string[] args)
{
bool lockTaken = false;
try
{
SpinLock.Enter(
ref lockTaken);
if (lockTaken)
Console.WriteLine(
"Lock taken");
}
finally
{
if (lockTaken)
SpinLock.Exit();
}
Console.WriteLine(
"Done");
}
}
}


So why would this single-threaded app tell me that the thread trying to call SpinLock.Exit() doesn’t hold the lock?



SpinLock is a value type.  When you mark a field referencing a reference type as readonly you are not only making the field unassignable but also implicitly making the value immutable.  To achieve this .NET will give you a copy of the value each time you read it rather than returning the original, that way if you change anything you will in fact be changing a copy.  So the call to SpinLock.Enter will execute on one copy of the SpinLock, and SpinLock.Exit will execute on a second copy and thus because they are separate instances the call to Exit will throw an exception because the current thread doesn’t hold a lock on it.



The solution is simple; remove readonly.

1 comment:

pappasmurf said...

Mr. Morris

Do you have a copy of the last version of FastStrings that you could send me along with any documentation.

I am converting an old Delphi7 application to DelphiXE3 and the customer cannot find the source code to FastStrings.

Also has anyone converted it to UniCode yet?


Thank you in advance.

Mark @ retalix dot com