覆盖C#的Monitor.Enter和Monitor.Exit

时间:2011-02-22 12:20:47

标签: c# multithreading operator-overloading override deadlock

我正在开发一个大的多线程项目,现在昨天我遇到了死锁(我的第一个),我通过添加Console.WriteLine(“FunctionName:Lock on VariableName”)和Console.WriteLine来跟踪它。 (“FunctionName:Unlocking VariableName”)。添加所有这些是相当有用的工作。

首先,程序有一个主循环,每秒运行2次,循环脉冲一些其他线程,以完成主循环处理后的工作。现在发生的事情是,我有一个处于等待状态的线程被激励,当它被脉冲时它称为另一个方法,它也等待脉冲,但脉冲已经发生,并且线程将不会再次脉冲直到动作实际上已经完成了。

现在我要做的是覆盖Monitor.Enter和Monitor.Exit函数,而不将它们包装在类中。
我听过很多关于Reflection的内容,但是我不知道如何将它应用于此目的,我知道实现它的最简单方法是使用包装类,但是后来lock关键字将不再起作用,我必须将所有锁转换为Monitor.Enter try {} finally {Monitor.Exit},这是大量的工作。

所以我的问题:如何覆盖Monitor.Enter和Monitor.Exit函数,同时保持对基本函数的访问以进行实际锁定?
如果这是不可能的:如何覆盖lock语句来调用我的包装类而不是Monitor.Enter和Monitor.Exit函数?

编辑清晰度:
我请求这只是为了让我在锁定发生时记录,使调试过程更容易,这也意味着我不想创建自己的锁定机制,我只想在锁定建立时记录< / em>当它发布时 只有当我遇到线程问题时,关闭也不会在大多数时间执行。

3 个答案:

答案 0 :(得分:3)

听起来你正在寻找锁定助手。 Jon Skeet的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的帮助程序,或者只是创建自己的帮助程序(用于记录目的等)。请查看上面的链接以获取更多信息。

答案 1 :(得分:2)

不要这样做!这听起来很疯狂; - )

当2个(或更多)线程都在等待同时保持2个(或更多)锁时,就会发生死锁。每个线程都会锁定并等待另一个线程。

你经常可以重新设计你的代码,这样每个线程只需要一个锁 - 这就不可能实现死锁。

如果失败了,你可以让一个线程放弃第一个锁,如果它无法获得第二个锁。

答案 2 :(得分:0)

这是一个非常糟糕的主意。我从来没有必要覆盖Monitor.Enter / Exit或锁定以克服死锁。请考虑重新设计代码!
例如,使用ManualResetEvent进行脉冲。