views:

27

answers:

2

Hi,

Given the following code:

...
private static SpinLock logLock = new SpinLock(false);
...

private static void ThreadFunc()
{
    bool lockTaken = false;
    logLock.Enter(ref lockTaken)
    {
        try
        {
            // do stuff with during an acquired SpinLock
        }
        finally
        {
            logLock.Exit();
        }
    }
}

If the Enter block "fails" because it receives a false on the lock being acquired, does the current thread spin like a spinlock and wait until it can acquire it or is this block simply bypassed and that thread loses out ?

Thanks,

Scott

+1  A: 

A SpinLock by definition causes the thread to spin while waiting to acquire for a lock rather than blocking. Enter does not "fail" if it can't acquire the lock, it just waits.

The only case where Enter may fail throwing an exception is when thread ownership is activated, using either new SpinLock() or new SpinLock(true). In this case an exception is thrown when a thread tries to acquire a lock it already owns. In your case this can never happen because you created the lock with tracking disabled (SpinLock(false)). If the thread tries to re-acquire the lock it will simply deadlock.

This is described in the documentation of the SpinLock.Enter method.

Panagiotis Kanavos
Thanks! You have confirmed my suspicions, as well as the thread debugger in VS 2010.
Scott Davies
+1  A: 

A SpinLock is basically just a loop around trying to set a variable to a specific value.

You could consider its implementation as follows:

public struct SpinLock
{
    private volatile bool _Locked;

    public void Acquire()
    {
        while (_Locked)
            ;
        _Locked = true;
    }

    public void Release()
    {
        _Locked = false;
    }
}

(of course, the above code is not thread-safe, and I know that's not the signature of the methods of the class, it's just a pseudo-code variant to show what it is doing)

So yes, if the SpinLock is already in a locked state, attempting to acquire it will spin until it becomes available.

Also, note that by default (as in your example), the struct does not keep track of who owns the lock. This means that if a thread tries to acquire the lock twice, it will deadlock with itself on the second attempt.

The purpose of SpinLock is to be a user-level lock with little overhead. It does not add GC pressure, nor does it allocate any kernel synchronization object, it's just a struct with a few fields.

Lasse V. Karlsen
Thank you! This is similar to a "hand rolled" example I saw in the book I'm reading, just before they discuss the actual .NET 4.0 BCL SpinLock. This reinforces what I needed to know.
Scott Davies