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

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

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

我只想检查它是否被锁定以及我的代码中的其他地方我将使用Monitor类来锁定对象。

我知道可以使用例如布尔字段(例如private bool ObjectIsLocked ),但是使用lock-object本身检测它。

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

 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); } } } 

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

无论如何,不​​要使用bool var来表示multithreading处于锁定状态(因为你可以有同样的问题,你读“假”和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); } 

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

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

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

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

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

使用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#通过multithreading更新更好地反映对它的更改。

如果您想确保以后对象仍然可以锁定,只需调用TryEnter并一直保持锁定。 否则,如果您想稍后尝试锁定对象,只需调用TryEnter并在锁定时立即解锁。

Techincally您可以检查对象的同步块索引字段,该字段在同步块数组中具有关联的延迟分配结构的索引 – 每个对象都有此字段,并且用于同步的每个对象都设置了此字段。 这些结构用于协调线程同步。 但是,我非常怀疑如果没有Profiling API ,您将能够访问此信息。

我绝不提倡检查锁然后输入代码块。 但是,我发现这个线程在寻找检查新函数的方法时无法锁定对象。 基于Monitor.IsEntered的unit testing让我得到了我正在寻找的东西。