Win32多线程之事件(Event Objects)


  Win32中最具弹性的同步机制就属events对象了。Event是一种核心对象,
  他的唯一目的就是成为激发状态或者未激发状态。这两种状态完全由程序来控制,
  不会成为Wait...()函数的副作用。
    Event对象之所以大有用途,正是因为它们的状态完全在你的控制之下。Mutexes和semaphores就不一样了。
它们的状态会因WaitForSingleObject()之类的函数调用而变化。所以,你可以精确告诉一个event对象做什么事,
以及什么时候去做。

Event对象可以用来设计你自己的同步对象。


HANDLECreateEvent(
LPSECURITY_ATTRIBUTES  lpEventAttributes,
BOOL  bManualReset,
BOOL  bInitialState,
LPCTSTR   lpName 
);


lpEventAttributes   安全属性。NULL 表示使用默认属性。
bManualReset       如为FALSE,表示这个event将在变成激发状态(因而唤醒一个线程)之后,自动重置(reset)为非激发状态。如果为TRUE,表示不会自动重置。必须
   靠程序操作(调用ResetEvent())才能将激发状态的event重置为非激发状态。
bInitialState  如果为TRUE,表示这个event一开始处于激发状态,如为FALSE,则表示这个event一开始处于非激发状态。
lpName    Event对象的名字,任何线程或进程都可以根据这个文字名称,使用这一event对象。


返回值
    如果调用成功,会传回一个event handle,GetLastError()会传回0.如果lpName所指定的event对象已经存在,CreateEvent()传回的是该event handle,而不会产生一个新的。这时候GetLastError()会传回ERROR_ALREADY_EXISTS。如果CreateEvent()失败,传回的是NULL,GetLastError()可以获得更进一步的失败信息。

操作系统会强迫让等待中的线程有轮番更替的机会,对于所有的同步机制,这都是一个重要的行为。如果操作系统没有强迫实现某种层次的公平性,可能会有某个线程不断获得执行机会,而某个线程一直未能获得CPU的青睐。这种情况被成为starvation(饥饿)。


如果你面对一个AutoReset对象调用SetEv()或PulseEvent(),而这时没有任何线程正在等待,会怎样?这种情况下这个event会被遗失。换句话说,除非有线程在等待,否则event不会被保存下来。这样的行为使得“要求苏醒”的请求很容易被遗失掉。例如,线程A累加一个计数器,之后调用WaitForSingleObject()等待一个event对象。如果在这些动作之间发生context切换,线程B起而执行,它检查计数器内容然后对着同一个event对象调用PulseEvent()。这时候,这个“要求苏醒”的请求会遗失掉。因为这个pulse不会被储存起来(因为还没有任何线程处于等待状态)。
另一种情况可能会引起死锁。假设“receiver”线程检查队列中是否有字符,这时候发生context switch,切换到“sender”线程,它对一个event对象进行pulse操作,这时候又发生context 切换,回到receiver线程,调用waitforSingleObject(),等待event对象,由于这个动作发生在sender线程激发event之后,所以event会遗失,于是receiver永远不会醒来,程序进入死锁状态,这正是semaphore之所以被创造用以解决问题的地方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值