开发者

Overriding C#'s Monitor.Enter and Monitor.Exit

开发者 https://www.devze.com 2023-02-12 20:17 出处:网络
I\'m working on some big multi threaded project, now yesterday I had a deadlock (my first one ever), and I traced it by adding a Console.WriteLine(\"FunctionName: Lock on VariableName\") and Console.W

I'm working on some big multi threaded project, now yesterday I had a deadlock (my first one ever), and I traced it by adding a Console.WriteLine("FunctionName: Lock on VariableName") and Console.WriteLine("FunctionName: Unlocking VariableName"). Adding all those was quite some work.

First of all, the program has a main loop that runs 2 times per second, that loop pulses some other threads to complete their work after the main loop has processed. Now what happened was that I had one thread in wait state to be pulsed, when it was pulsed it called another method that'd also wait to get pulsed, but the pulse already happened, and the thread won't pulse again until the action is actually completed.

Now what I want to do is override the Monitor.Enter and Monitor.Exit functions, without wrapping them in a class.

I've heard a lot about Reflection, but I have no idea how to apply it for this purpose, I know the easiest way to achieve it all is by just using a wrapper class, but then the lock keyword won't work anymore, and I'd have to convert all locks into Monitor.Enter try { } finally { Monitor.Exit }, that's huge amount of work.

So my question: How to override the Monitor.Enter and Monitor.Exit functions, while keeping access to the base function to do the actual lock?

And if that's impossible: How to override the lock statement to call my wrapper class instead of the Monitor.Enter and Monitor.Exit functions?

EDIT FOR CLARITY:

I request this just for allowing me to log when the locks happen, to make the debugging process easier, that also means I don't want to create my own locking mechanism, I just want to log when a lock is established and when it's released.

T开发者_JAVA技巧he close will also not be executed most of the time, only when I come across a threading problem.


It sounds like you're looking for lock helpers. Jon Skeet's MiscUtil has some: http://www.yoda.arachsys.com/csharp/miscutil/usage/locking.html

The idea is that you replace your lock statements with using statements and thus preserve the try-finally structure:

class Example
{
    SyncLock padlock = new SyncLock();

    void Method1
    {
        using (padlock.Lock())
        {
            // Now own the padlock
        }
    }      

    void Method2
    {
        using (padlock.Lock())
        {
            // Now own the padlock
        }
    }
}

With regards to deadlock prevention, the library offers a specialized ordered lock:

class Example
{
    OrderedLock inner = new OrderedLock("Inner");
    OrderedLock outer = new OrderedLock("Outer");

    Example()
    {
        outer.InnerLock = inner;
    }
}

Of course, you could extend Jon's helpers, or simply create your own (for logging purposes, etc). Check out the link above for more information.


Don't do it! That sounds bonkers ;-)

A deadlock occurs when 2 (or more) threads are all waiting to simultaneously hold 2 (or more) locks. And each thread gets a lock and waits for the other one.

You can often redesign your code so each thread only requires a single lock - which makes deadlock impossible.

Failing that, you can make a thread give up the first lock if it can't acquire the second lock.


That's a very bad idea. I never had to override Monitor.Enter / Exit or lock to overcome a deadlock. Please consider redesigning your code!
For example, use ManualResetEvent for the pulsing.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号