如何检测物体是否被锁定?
Monitor.TryEnter
(如Is there a way to detect if an object is locked?中所述)对我不起作用,因为如果对象未锁定,它会锁定对象。
我只想要检查它是否已被锁定以及我的代码中的其他位置我将使用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);
}
}
}
答案 0 :(得分:43)
你做错了。如果您没有锁定对象,则无法检查它是否已锁定(如果您有锁,则可以提前知道)。你可以“问”“被锁定了吗?”并得到一个“不”作为响应,然后在下一个纳秒,另一个线程可以采取锁定,你的程序将进入一个损坏的状态。这根本不是继续使用多线程应用程序以及.NET没有Monitor.IsLocked
方法的原因。如果您的代码需要在获取之前检查锁定,那么您就会遇到设计问题。尝试使用不受保护的标志解决它是一个糟糕的解决方案,100%的机会无法保证。
无论如何,不要使用bool
var来表示多线程被锁定状态(因为你可能有同样的问题,你读“假”和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,可以获取对象的锁定。换句话说,您将围绕本机锁定系统构建一个自定义锁定系统。
答案 1 :(得分:8)
答案 2 :(得分:5)
使用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#更好地反映对多线程更新的更改。
答案 3 :(得分:0)
如果您想确保以后对象仍然可以锁定,只需调用TryEnter
并一直保持锁定。否则,如果您想稍后尝试锁定对象,只需致电TryEnter
并在锁定时立即解锁。
答案 4 :(得分:0)
Techincally您可以检查对象的同步块索引字段,该字段在同步块数组中具有关联的延迟分配结构的索引 - 每个对象都有此字段和每个对象,用于同步的,具有此字段集。这些结构用于协调线程同步。但是,我非常怀疑,如果没有 Profiling API ,您将能够访问此信息。
答案 5 :(得分:-1)
我绝不提倡检查锁然后输入代码块。但是,我发现这个线程在寻找检查新函数的方法时无法锁定对象。基于Monitor.IsEntered的单元测试让我得到了我正在寻找的东西。