我有一个在 C++ 中很容易解决的问题,但在 C# 中我仍然找不到一个好的解决方案:
我有一个函数 foo 需要锁定两个对象,并且可以使用相反顺序的参数调用此函数,例如:
static void foo(object o1, object o2)
{
lock (o1)
{
lock (o2)
{
...
}
}
}
static void bar(object a, object b)
{
ThreadPool.QueueUserWorkItem(s => foo(a, b));
ThreadPool.QueueUserWorkItem(s => foo(b, a));
}
这是造成僵局的一种循规蹈矩的方法。解决此问题的标准方法是始终以相同的顺序锁定对象。在 C++ 中,我可以比较指针,但在“安全”的 C# 中,我除了一个非常丑陋的解决方案之外我不知道任何方法Monitor.TryEntry
(见下文)。有更好的吗?请注意,对象是可变的,我不能依赖Equals
, GetHashCode
, IComparable
。
static void foo(object o1, object o2)
{
const int Timeout = 1000;
while (true)
{
if (Monitor.TryEnter(o1, Timeout))
{
try
{
if (Monitor.TryEnter(o2, Timeout))
{
try
{
...
return;
}
finally
{
Monitor.Exit(o2);
}
}
}
finally
{
Monitor.Exit(o1);
}
}
}
}