c# – 监视vs基于WaitHandle的线程同步

我的印象是,阅读this article后,最好使用Monitor / Lock进行线程同步,因为它不使用本机资源

具体报价(摘自本文第5页):

Monitor.Wait/Pulse isn’t the only way of waiting for something to happen in one thread and telling that thread that it’s happened in another. Win32 programmers have been using various other mechanisms for a long time, and these are exposed by the AutoResetEvent, ManualResetEvent and Mutex classes, all of which derive from WaitHandle. All of these classes are in the System.Threading namespace. (The Win32 Semaphore mechanism does not have a managed wrapper in .NET 1.1. It’s present in .NET 2.0, but if you need to use it before then, you could either wrap it yourself using P/Invoke, or write your own counting semaphore class.)

Some people may be surprised to learn that using these classes can be significantly slower than using the various Monitor methods. I believe this is because going “out” of managed code into native Win32 calls and back “in” again is expensive compared with the entirely managed view of things which Monitor provides. A reader has also explained that monitors are implemented in user mode, whereas using wait handles require switching into kernel mode, which is fairly expensive.

但是自从发现SO并在这里阅读一些问题/答案后,我开始怀疑我对何时使用每一个的理解。看起来很多人推荐在Monitor.Wait / Pulse会做的情况下使用Auto / ManualResetEvent。任何人都可以向我解释当WaitHandle基于同步应该使用监视器?

谢谢

Monitor.Pulse / Wait的问题是信号可能丢失。

例如:

var signal = new ManualResetEvent(false);

// Thread 1
signal.WaitOne();

// Thread 2
signal.Set();

这将总是工作,不管在不同线程中的两个语句被执行。它也是一个非常干净的抽象,并非常清楚地表达你的意图。

现在看看使用显示器的同一个例子:

var signal = new object();

// Thread 1
lock (signal)
{
    Monitor.Wait(signal);
}

// Thread 2
lock (signal)
{
    Monitor.Pulse(signal);
}

如果在Wait之前执行Pulse,信号(脉冲)将丢失。

要解决这个问题,你需要这样的:

var signal = new object();
var signalSet = false;

// Thread 1
lock (signal)
{
    while (!signalSet)
    {
        Monitor.Wait(signal);
    }
}

// Thread 2
lock (signal)
{
    signalSet = true;
    Monitor.Pulse(signal);
}

这工作,可能是更高性能和轻量级,但是更少的可读性。这就是头痛叫并发的地方。

>这段代码真的有效吗?
>在每个角落里?
>有两个以上的线程? (提示:没有)
>你如何单元测试呢?

坚实,可靠,可读的抽象通常比原始性能更好。

此外,WaitHandles提供了一些不错的东西,如等待一组句柄设置等。用监视器实现这一点头疼更糟…

经验法则:

>使用监视器(锁)确保对共享资源的独占访问
>使用WaitHandles(Manual / AutoResetEvent / Semaphore)在线程之间发送信号

http://stackoverflow.com/questions/1355398/monitor-vs-waithandle-based-thread-sync

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c# – 监视vs基于WaitHandle的线程同步