Test a lock with out acquiring it? Test a lock with out acquiring it? multithreading multithreading

Test a lock with out acquiring it?


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.


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.