C# How to detect an object is already locked

前端 未结 6 743
孤独总比滥情好
孤独总比滥情好 2020-12-08 19:31

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 f

相关标签:
6条回答
  • 2020-12-08 19:59

    I can in no way advocate checking locks then entering code blocks. However, I found this thread while looking for a way to check a new function couldn't leave an object locked. A unit test based on Monitor.IsEntered got me exactly what I was looking for.

    0 讨论(0)
  • 2020-12-08 20:03

    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.

    0 讨论(0)
  • 2020-12-08 20:05

    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.

    0 讨论(0)
  • 2020-12-08 20:10

    If you want to ensure the object is still lockable later on, just call TryEnter and hold the lock the whole time. Otherwise, if you want to try to lock the object later, just call TryEnter and immediately unlock it if it's locked.

    0 讨论(0)
  • 2020-12-08 20:14

    Monitor.IsEntered should do the trick.

    Edit: I just re-read the documentation, and it says:

    Determines whether the current thread holds the lock on the specified object.

    So that is not sufficient, as you would probably like to know if a different thread holds a lock?

    0 讨论(0)
  • 2020-12-08 20:16

    Techincally you can check for object's Sync Block Index field which has an index of associated lazily allocated structure in Sync Blocks array - every object has this field and every object, which used for synchronziation, has this field set. These structures are used to coordinate thread synchronization. However, I highly doubt that you'll be able to access this information without Profiling API.

    0 讨论(0)
提交回复
热议问题