PulseEvent使用说明

最近一直在看《windwos核心编程》,关于线程同步,有这样一个函数PulseEvent().

在MSDN上解释如下:

      This function provides a single operation that sets to signaled the state of the specified event object and then resets it to nonsignaled after releasing the appropriate number of waiting threads.

      (这个函数设置特定的事件对象为有信号状态,然后释放相关的等待线程,再置时间对象为无信号状态)

但是MSDN又说了,这个函数是不好的,最好不要使用。

       对于Event对象,我们知道,分手动重置和自动重置两种。手动重置Event,需要认为控制信号的有无,可以有多个线程等待同一个Event对象,当变成有信号状态时,等待的各个线程都可以被激活。那么对于自动重置事件,激活其中一个线程之后会自动变成无信号状态,几个竞争的线程只能有一个获得激活。

      然而,在使用PulseEvent()的时候却发现,等待的线程并不能都被激活,那么,究竟发生了什么呢?

 

 

     SignalSemaphore(hOtherSemaphore);
     WaitForSingleObject(hEvent, INFINITE);

事实上,这并不总是正确的。因为在信号和等待之间存在竞争,如果在一个线程PluseEvent()的时候,恰好没有线程处于等待状态,那么这个事件将丢失!

这是我在网上搜到的一段话:

 

     While the thread is sitting waiting for the event, a device driver or part of the kernel itself might ask to borrow the thread to do some processing (by means of a "kernel-mode APC"). During that time, the thread is not in the wait state. (It's being used by the device driver.) If the PulseEvent happens while the thread is being "borrowed", then it will not be woken from the wait, because the PulseEvent function wakes only threads that were waiting at the time the PulseEvent occurs.

很好的解释了这种现象的原因,原来一个线程处于等待状态的过程中,会有一些瞬间其状态并不为“等待状态”。这就造成PulseEvent()不能激活应该被激活的等待线程。

     这些瞬间包括什么呢?比如发生了系统调用,缺页中断,硬件中断......等等。

     怎么解决这个问题呢?MSDN建议使用SiginalObjectAndWait()。具体信息可以查询MSDN.

     终于知道为什么PulseEvent()是不可靠的了:)

看下面的代码,你是否以为会如你所愿的进行?

你可能感兴趣的:(thread,编程,function,object,processing)