C#如何检测对象已被锁定

hwc*_*rwe 34 c# multithreading locking .net-4.0

如何检测对象是否被锁定?

Monitor.TryEnter(如有没有办法检测对象是否被锁定?)对我不起作用,因为它锁定了对象(如果没有锁定).

只是想检查,如果它被锁定,其他地方在我的代码,我将使用Monitor类锁定对象.

我知道可以使用例如布尔字段(例如private bool ObjectIsLocked)但是使用锁定对象本身来检测它.

下面的示例代码显示了我想要做的事情:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*Zen 45

你做错了.如果你没有锁定物体,你就无法检查它是否被锁定(如果你有锁,你会提前知道).你可以"问""被锁定了吗?" 并得到一个"不"作为响应,然后在下一个纳秒,另一个线程可以采取锁定,你的程序将进入一个损坏的状态.这根本不是继续使用多线程应用程序以及.NET没有Monitor.IsLocked方法的原因.如果您的代码需要在获取之前检查锁定,那么您就会遇到设计问题.尝试使用不受保护的标志解决它是一个糟糕的解决方案,100%的机会保证不起作用.

无论如何,不​​要使用boolvar来表示多线程处于锁定状态(因为你可以有同样的问题,你读"假"和1纳秒后,另一个线程会写"真"到它).使用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);
}
Run Code Online (Sandbox Code Playgroud)

您将看到在需要锁定对象的每个位置都需要更改_lockFlag .换句话说,您将围绕本机锁定系统构建一个自定义锁定系统.

  • 那你会对这个场景有什么建议?我正在做一个文件管理器.我是多线程获取自定义FileItems因为构造是非平凡的.我想尽可能多地构建这些FileItem,但我想尽可能地响应前端.因此,如果更新UI的线程被锁定,只需继续获取FileItems.如果没有,请在列表中发出当前未完成的信号.这样,处理不依赖于锁 (2认同)

Pet*_*ete 8

Monitor.IsEntered应该可以解决问题.

编辑:我只是重新阅读文档,它说:

确定当前线程是否保持对指定对象的锁定.

所以这还不够,因为你可能想知道一个不同的线程是否持有锁?


Ivo*_*ops 5

使用C#中的Monitor类无法做到这一点

只是用;

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

像readerwriterlockslim这样的其他锁定并没有真正帮助.那个人可以告诉你那里的读者怎么样,但如果有作家忙的话就不会;-(

如果您使用自己的建议'private bool ObjectIsLocked',这是我认为的路线,你应该使用

      private volatile bool ObjectIsLocked
Run Code Online (Sandbox Code Playgroud)

这将使C#通过多线程更新更好地反映对它的更改.

  • try-finally块可以提高正确性. (2认同)