您可能遇到过的lock(someObject) 语句是Monitor.Enter 和Monitor.Exit 周围的语法糖。
但是,如果您以这种更详细的方式使用监视器,您还可以使用Monitor.TryEnter,它允许您检查您是否能够获得锁定 - 从而检查其他人是否已经拥有它并正在执行代码。
所以不要这样:
var lockObject = new object();
lock(lockObject)
{
// do some stuff
}
试试这个(选项 1):
int _alreadyBeingExecutedCounter;
var lockObject = new object();
if (Monitor.TryEnter(lockObject))
{
// you'll only end up here if you got the lock when you tried to get it - otherwise you'll never execute this code.
// do some stuff
//call exit to release the lock
Monitor.Exit(lockObject);
}
else
{
// didn't get the lock - someone else was executing the code above - so I don't need to do any work!
Interlocked.Increment(ref _alreadyBeingExecutedCounter);
}
(你可能想尝试一下..finally 以确保释放锁)
或完全放弃显式锁定并执行此操作
(选项 2)
private int _inUseCount;
public void MyMethod()
{
if (Interlocked.Increment(ref _inUseCount) == 1)
{
// do dome stuff
}
Interlocked.Decrement(ref _inUseCount);
}
[编辑:回答您关于this的问题]
不 - 不要使用 this 到 lock。创建一个私有范围的对象作为您的锁。
否则你有这个潜在的问题:
public class MyClassWithLockInside
{
public void MethodThatTakesLock()
{
lock(this)
{
// do some work
}
}
}
public class Consumer
{
private static MyClassWithLockInside _instance = new MyClassWithLockInside();
public void ThreadACallsThis()
{
lock(_instance)
{
// Having taken a lock on our instance of MyClassWithLockInside,
// do something long running
Thread.Sleep(6000);
}
}
public void ThreadBCallsThis()
{
// If thread B calls this while thread A is still inside the lock above,
// this method will block as it tries to get a lock on the same object
// ["this" inside the class = _instance outside]
_instance.MethodThatTakesLock();
}
}
在上面的例子中,一些外部代码已经设法破坏了我们类的内部锁定,只是通过对外部可访问的东西进行锁定。
最好创建一个您可以控制的私有对象,并且您的班级之外的任何人都无法访问,以避免此类问题;这包括不使用this 或类型本身typeof(MyClassWithLockInside) 进行锁定。