关于线程同步 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()是不可靠的了:)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值