重写C#的Monitor.Enter和Monitor.Exit
我正在研究一些大的多线程项目,现在我昨天遇到了一个死锁(我的第一个死锁),并通过添加Console.WriteLine(“FunctionName:Lock on VariableName”)和Console.WriteLine(“FunctionName :解锁VariableName“)。 添加所有这些都是一些工作。
首先,该程序有一个每秒运行2次的主循环,该循环会在主循环处理完毕后触发一些其他线程完成其工作。 现在发生的事情是,我有一个处于等待状态的线程被脉冲化,当它被脉冲称为另一种方法时,它也会等待脉冲,但脉冲已经发生,并且线程不会再次脉冲,直到动作实际上已经完成。
现在我想要做的就是覆盖Monitor.Enter和Monitor.Exit函数,而不用将它们包装在一个类中。
我听说过很多关于Reflection的内容,但我不知道如何将其应用于此目的,我知道实现它的最简单方法是仅使用包装类,但随后lock关键字不再起作用,我必须将所有锁转换为Monitor.Enter,最后{Monitor.Exit},这是大量的工作。
所以我的问题:如何重写Monitor.Enter和Monitor.Exit函数,同时保持对基函数的访问来执行实际的锁定?
如果这是不可能的:如何覆盖锁定语句来调用我的包装类而不是Monitor.Enter和Monitor.Exit函数?
编辑清晰:
我请求这只是为了让我记录锁发生时的情况,使调试过程更加简单,这也意味着我不想创建自己的锁定机制,我只想记录锁何时建立以及何时发布。
只有当我遇到线程问题时,关闭也不会在大部分时间执行。
不要这样做! 这听起来好疯狂;-)
当2个(或更多)线程都在等待同时持有2个(或更多)锁时发生死锁。 每个线程获得一个锁并等待另一个线程。
你经常可以重新设计你的代码,这样每个线程只需要一个锁 - 这使得死锁成为不可能。
否则,如果线程无法获取第二个锁,则可以让线程放弃第一个锁。
这听起来像你正在寻找锁定帮手。 Jon Skeet的MiscUtil有一些:http://www.yoda.arachsys.com/csharp/miscutil/usage/locking.html
这个想法是,你用using
语句来替换你的lock
语句,从而保留try-finally结构:
class Example
{
SyncLock padlock = new SyncLock();
void Method1
{
using (padlock.Lock())
{
// Now own the padlock
}
}
void Method2
{
using (padlock.Lock())
{
// Now own the padlock
}
}
}
关于预防死锁,图书馆提供了一个专门的有序锁定:
class Example
{
OrderedLock inner = new OrderedLock("Inner");
OrderedLock outer = new OrderedLock("Outer");
Example()
{
outer.InnerLock = inner;
}
}
当然,你可以扩展Jon的助手,或者简单地创建你自己的(为了记录目的等)。 查看上面的链接了解更多信息。
这是一个非常糟糕的主意。 我从来不必重写Monitor.Enter / Exit或锁定以克服死锁。 请考虑重新设计您的代码!
例如,使用ManualResetEvent
作为脉冲。