我有一些对象,它们被锁定了。我想在不获取锁的情况下测试它们是否被锁定。我的想法是如果我使用
这似乎是一个非常基本的问题,应该如何解决?
TryEnter()
,然后如果返回值为 true
,则必须使用 Exit()
来正确检查锁。这似乎是一个非常基本的问题,应该如何解决?
TryEnter()
,然后如果返回值为 true
,则必须使用 Exit()
来正确检查锁。当您看到锁被解锁时,您可以从中获得什么信息?但在您根据这些信息做出决定时,锁可能已经被拿走了。
因为lock语句等同于:
System.Threading.Monitor.Enter(x);
try {
...
}
finally {
System.Threading.Monitor.Exit(x);
}
你能做到这个吗?
bool ObjectWasUnlocked(object x)
{
if(System.Threading.Monitor.TryEnter(x))
{
System.Threading.Monitor.Exit(x);
return true;
}
else
{
return false;
}
}
在尝试审计我的代码以确保正确的锁定时,我也在思考同样的问题。我想出了一种使用第二个线程的方法。如果调用线程可以访问锁,但第二个线程无法访问,则必须由第一个线程持有。
/// <summary>
/// Utiltity for checking if a lock has already been acquired.
/// WARNING: This test isn't actually thread-safe,
/// it's only really useful for unit tests
/// </summary>
private static bool ObjectIsAlreadyLockedByThisThread(object lockObject)
{
if (!Monitor.TryEnter(lockObject))
{
// another thread has the lock
return false;
}
Monitor.Exit(lockObject);
bool? LockAvailable = null;
var T = new Thread(() =>
{
if (Monitor.TryEnter(lockObject))
{
LockAvailable = true;
Monitor.Exit(lockObject);
}
else
{
LockAvailable = false;
}
});
T.Start();
T.Join();
return !LockAvailable.Value;
}
// Tests:
public static void TestLockedByThisThread()
{
object MyLock = new object();
lock (MyLock)
{
bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);
Debug.WriteLine(WasLocked); // prints "True"
}
}
public static void TestLockedByOtherThread()
{
object MyLock = new object();
var T = new Thread(() =>
{
lock (MyLock)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
}
});
T.Start();
Thread.Sleep(TimeSpan.FromSeconds(1));
bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);
T.Join();
Debug.WriteLine(WasLocked); // prints "False"
}
public static void TestNotLocked()
{
object MyLock = new object();
bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);
Debug.WriteLine(WasLocked); // prints "False"
}
我不会在生产代码中使用这个 - 存在一种竞争条件可能导致程序崩溃。然而,我的单元测试大多是单线程的,因此这很有用。
finally
块中的第一个Monitor.Exit(lockObject)
也会被调用。 - Sebastian Krysmanski