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%的机会保证不起作用.
无论如何,不要使用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);
}
Run Code Online (Sandbox Code Playgroud)
您将看到在需要锁定对象的每个位置都需要更改_lockFlag .换句话说,您将围绕本机锁定系统构建一个自定义锁定系统.
使用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#通过多线程更新更好地反映对它的更改.