我正在处理一个大型多线程项目,昨天我遇到了一个死锁(这是我的第一个死锁),我通过添加一个Console.WriteLine("FunctionName: Lock on VariableName")和Console.WriteLine("FunctionName: Unlocking“)来跟踪它。把所有这些都加进去是一项相当大的工作。
首先,程序有一个主循环,每秒运行2次,该循环在主循环处理后执行一些其他线程来完成它们的工作。现在发生的是,我有一个线程处于等待状态被脉冲,当它被脉冲时,它被称为另一个方法,它也会等待被脉冲,但是脉冲已经发生了,直到动作完成,线程才会再次脉冲。
现在,我要做的是重写Monitor.Enter和Monitor.Exit函数,而不将它们包装在类中。
我听说过很多关于反射的事情,但是我不知道如何将它应用于这个目的,我知道实现反射的最简单的方法就是使用一个包装类,但是这样锁关键字就不能再工作了,我必须将所有锁转换为Monitor.Enter try {}--最后是{ Monitor.Exit },这是一项巨大的工作。
那么,我的问题是:如何覆盖Monitor.Enter和Monitor.Exit函数,同时保持对基本函数的访问来执行实际的锁?
如果这是不可能的:如何覆盖lock语句来调用我的包装类而不是Monitor.Enter和Monitor.Exit函数?
清晰的编辑:
我请求这样做只是为了允许我在锁发生时进行日志记录,从而简化调试过程,这也意味着我不想创建自己的锁定机制,我只想在建立锁和释放锁时进行记录。
关闭也不会在大多数情况下执行,只有在遇到线程问题时才会执行。
发布于 2011-02-22 12:29:48
不要这么做!听起来很疯狂;-)
当两个(或更多)线程都在等待同时持有两个(或更多)锁时,就会发生死锁。每个线程得到一个锁,然后等待另一个锁。
您通常可以重新设计代码,因此每个线程只需要一个锁--这使得死锁不可能发生。
如果失败,您可以让线程放弃第一个锁,如果它不能获得第二个锁。
发布于 2011-02-22 12:31:43
听起来你在找锁具帮手。乔恩·斯基特的MiscUtil有一些:http://www.yoda.arachsys.com/csharp/miscutil/usage/locking.html
这样做的想法是将lock语句替换为using语句,从而保留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的助手,也可以简单地创建自己的(用于日志记录等)。有关更多信息,请查看上面的链接。
发布于 2011-02-22 12:23:27
那是个很糟糕的主意。我从来不需要重写Monitor.Enter /退出或锁定来克服死锁。请考虑重新设计您的代码!
例如,使用ManualResetEvent作为脉冲。
https://stackoverflow.com/questions/5078030
复制相似问题