Question

I have objects, they get locks. I want to test if they are locked without acquiring a lock. The idea is if I TryEnter() then i have to Exit() if true to only check the lock correctly.

Seems like a really basic question, how is it done?

Was it helpful?

Solution

What possible information can you get from knowing the lock was unlocked back when you looked at it? By the time you make a decision based on that information, the lock may be already taken.

OTHER TIPS

Because the lock statement is equivalent to:

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

Can you just do this?

bool ObjectWasUnlocked(object x)
{
   if(System.Threading.Monitor.TryEnter(x))
   {
       System.Threading.Monitor.Exit(x);
       return true;
   }
   else
   {
       return false;
   }
}

Note that I'm naming this function "ObjectWasUnlocked" as opposed to "ObjectIsUnlocked". There is no guarantee that it will still be unlocked when the function has returned.

I was wondering the same thing while trying to audit my code for correct locking. I came up with a method using a second thread. If the lock is available to the calling thread, but unavailable to a second thread, it must be held by the first.

    /// <summary>
/// Utiltity for checking if a lock has already been acquired.
/// WARNING: This test isn't actually thread-safe, 
/// it's only really useful for unit tests
/// </summary>
private static bool ObjectIsAlreadyLockedByThisThread(object lockObject)
{
    if (!Monitor.TryEnter(lockObject))
    {
        // another thread has the lock
        return false;
    }

    Monitor.Exit(lockObject);

    bool? LockAvailable = null;

    var T = new Thread(() =>
    {
        if (Monitor.TryEnter(lockObject))
        {
            LockAvailable = true;
            Monitor.Exit(lockObject);
        }
        else
        {
            LockAvailable = false;
        }
    });

    T.Start();

    T.Join();

    return !LockAvailable.Value;
}

// Tests:
public static void TestLockedByThisThread()
{
    object MyLock = new object();
    lock (MyLock)
    {
        bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);

        Debug.WriteLine(WasLocked); // prints "True"
    }
}

public static void TestLockedByOtherThread()
{
    object MyLock = new object();

    var T = new Thread(() =>
    {
        lock (MyLock)
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }
    });

    T.Start();
    Thread.Sleep(TimeSpan.FromSeconds(1));

    bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);

    T.Join();

    Debug.WriteLine(WasLocked); // prints "False"
}

public static void TestNotLocked()
{
    object MyLock = new object();

    bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);

    Debug.WriteLine(WasLocked); // prints "False"
}

I wouldn't use this in production code - there's a race condition that could blow up. However, my unit tests are mostly single threaded, so this was useful.

Here is a related question

Checking whether the current thread owns a lock

The conclusion there was 'you can't'

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top