C# 如何检测对象是否已锁定

问题描述 投票:0回答:6

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

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

only想检查它是否被锁定,并且在我的代码中的其他地方我将使用

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);
        }
    }
}
c# multithreading .net-4.0 locking
6个回答
59
投票

你做错了。如果你没有对象上的锁,你就无法检查它是否被锁定(如果你有锁,你会提前知道)。你可以“问”“被锁了吗?”并得到“不”作为响应,然后在下一个纳秒另一个线程可以获取锁定,并且您的程序将处于损坏状态。这根本不是多线程应用程序的方式,也是 .NET 没有

Monitor.IsLocked
方法的原因。如果您的代码需要在获取锁之前检查锁,那么您就遇到了设计问题。尝试使用不受保护的标志来解决这个问题是一个糟糕的解决方案,100% 的可能性是行不通的。

无论如何,不要使用

bool
var 来表示多线程已锁定状态(因为您可能会遇到同样的问题,您读取“false”,1纳秒后另一个线程将向其写入“true”)。使用
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);
}

您会发现您需要在每个可以获取对象锁的地方更改_lockFlag。换句话说,您将围绕本机锁定系统构建一个自定义锁定系统。


12
投票

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

只需使用;

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

其他锁(例如 readerwriterlockslim)并没有真正的帮助。那个人可以告诉你有多少读者,但不能告诉你是否有一位作家很忙;-(

如果您使用自己的建议“private bool ObjectIsLocked”,这是我认为我会采取的路线,您应该使用

      private volatile bool ObjectIsLocked

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


10
投票

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

编辑:我刚刚重新阅读了文档,它说:

判断当前线程是否持有指定的锁 对象。

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


0
投票

如果您想确保该对象稍后仍可锁定,只需调用

TryEnter
并始终保持锁定即可。否则,如果您想稍后尝试锁定该对象,只需调用
TryEnter
并在锁定时立即解锁。


0
投票

从技术上讲,您可以检查对象的 Sync Block Index 字段,该字段具有 Sync Blocks array 中关联的延迟分配结构的索引 - 每个对象都有此字段,并且用于同步的每个对象都设置有此字段。这些结构用于协调线程同步。但是,我非常怀疑您是否能够在没有 Profiling API 的情况下访问此信息。


-3
投票

我绝不提倡检查锁然后输入代码块。然而,我在寻找一种方法来检查新函数不能锁定对象时发现了这个线程。基于 Monitor.IsEntered 的单元测试让我得到了我想要的东西。

© www.soinside.com 2019 - 2024. All rights reserved.