Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# How to detect an object is already locked

How can I detect whether an object is locked or not?

Monitor.TryEnter (as described in Is there a way to detect if an object is locked?) does not work for me because it locks the object if it is not locked.

I only want to check if it is locked and somewhere else in my code I will use the Monitor class to lock the object.

I know it is possible to use for example an boolean field (for example private bool ObjectIsLocked) but what to detect it using the lock-object itself.

The example code below shows what I want to do:

private static object myLockObject = new object();  private void SampleMethod() {     if(myLockObject /*is not locked*/) // First check without locking it     {         ...         // The object will be locked some later in the code         if(!Monitor.TryEnter(myLockObject)) return;          try         {              ....         }         catch(){...}         finally         {             Monitor.Exit(myLockObject);         }     } } 
like image 555
hwcverwe Avatar asked Aug 20 '12 07:08

hwcverwe


2 Answers

You're doing it wrong. If you don't have the lock on the object you can't check if it is locked (and if you have the lock you will know in advance). You can "ask" "is locked?" and get a "not" as response, then on the next nanosecond another thread can take the lock and your program will enter in a corrupted state. This simply is not the way to go on multithreaded apps and the reason why .NET does not have a Monitor.IsLocked method. If your code needs to check the lock before acquire it so you have a design problem. Trying to solve it with unprotected flags is a poor solution that is guaranteed by 100% of chance that will not work.

Anyway, do not use a bool var to signal multi-thread is locked state (because you can have the same problem, you read "false" and 1 nanosecond later another thread will write "true" to it). Use Interlock.CompareExchange.

private static int _lockFlag = 0; // 0 - free  if (Interlocked.CompareExchange(ref _lockFlag, 1, 0) == 0){    // only 1 thread will enter here without locking the object/put the    // other threads to sleep.     Monitor.Enter(yourLockObject);      // free the lock.    Interlocked.Decrement(ref _lockFlag); } 

You'll see that you'll need to change the _lockFlag on every place where a lock to your object could be aquired. In other words, you'll construct a custom lock system around the native one.

like image 96
Marcelo De Zen Avatar answered Sep 19 '22 11:09

Marcelo De Zen


There is no way to do this with the Monitor class in C#

Just use;

    var lockedBySomeoneElse = !Monitor.TryEnter(obj);     if (!lockedBySomeoneElse) Monitor.Exit(obj);     // the variable 'lockedBySomeoneElse' has the info you want 

Other locks like readerwriterlockslim do not really help. That one can tell you how may readers there are, but not if there is a writer busy ;-(

also if you use your own suggestion 'private bool ObjectIsLocked', which is the route I would take I think, you should use

      private volatile bool ObjectIsLocked 

This will make C# reflect changes to it better with multithread updates.

like image 22
IvoTops Avatar answered Sep 20 '22 11:09

IvoTops