NiloCK
NiloCK

Reputation: 621

How to make a method which only runs if the calling thread holds a lock?

In my unsafe class below, what can be done to prevent someone from executing the unsafe method without first obtaining the lock?

class Unsafe
{
    private static readonly object lockObj;

    void MethodA()
    {
        lock (lockObj)
        {
            // do some things
            DoUnsafeThing();
        }
    }

    void MethodB()
    {
        lock (lockObj)
        {
            // do some things
            DoUnsafeThing();
        }
    }

    void DoUnsafeThing()
    {
        if (callerHasLock)
            // Do the unsafe thing
        else
            return; // or throw some exception
    }
}

Obtaining the lock again inside DoUnsafeThing() is an option:

void DoUnsafeThing()
{
    lock (lockObj)
    {
        // Do the unsafe thing
    }
}

But DoUnsafeThing() can now be called by threads that don't already possess the lock.

Upvotes: 2

Views: 1018

Answers (1)

Marc L.
Marc L.

Reputation: 3399

You should be able to use Monitor.IsEntered() to verify that the thread itself has already obtained the lock:

void DoUnsafeThing()
{
    if (Monitor.IsEntered(lockObj))
        // Do the unsafe thing
    else
        return; // or throw some exception
}

You can use the Monitor class to work with locks. In C#, the lock(...) statement is just syntactic sugar for Monitor.Enter(o); try {...} finally {Monitor.Exit(o);}. There are other options within it for fine-tuning. Remember, multi-threading is Hard. Know your toolset.

EDIT: (in response to framework version question update)

Prior to .NET 4.5, AFAIK the only way to handle this would be to use a thread-static Boolean alongside the synchronization object, set to true just after entering and false just before exiting. That same Boolean--call it callerHasLock, to conform with your code above--can then be tested within the lock context with the same result as Monitor.IsEntered.

Upvotes: 5

Related Questions