多线程开发学习笔记之线程同步——事件

        事件,在我看来就是一种触发机制,即满足某一条件的触发。当线程需要等待某一事件的发生而不是一个资源的解锁,这在接收网络信息包或等待一个已完成某些任务的线程发出信号时非常有用。在Win32系统中,提供了事件对象。事件对象是同步对象中最简单的形式,也是最具有弹性的同步机制。其与互斥量和信号量的区别在于:互斥量和信号量是用于对数据的访问的,而事件是用来发信号表示某一操作已经完成了。事件对象是一种核心对象,它的惟一目的就是成为激发状态或未激发状态,这两种状态完全由程序来控制,不会成为等待函数的副作用。

        有两种事件对象:一、人工重置。其作用是向几个线程同时发信号,表示某一操作已经完成;二、自动重置。其作用是向一个线程发信号,表示某一操作已经完成。

        线程常用用途:事件最常用于一个线程进行初始化工作后,发信号给另一个线程,让其完成剩余的工作。初始化线程将事件设置为无信号状态后开始进行初始化,而后,当初始化完成后,线程把事件设置为有信号状态。当工作线程开始工作时,它立即自我挂起,等待事件变为有信号。当初始化线程把事件设置为有信号状态后,工作县城就醒来执行余下的必要工作。

        例如,一个线程运行了两个线程。第一个线程从文件中读取数据到内存缓冲区,在数据读完后,它就发信号给第二个线程告诉它可以处理数据了。当第二个线程完成了对数据的处理后,它就需要再给第一个线程发信号,以便使第一个线程能从文件中读取下一块数据。

        Win32 API产生事件对象的函数原型如下:

/* Brief 创建事件对象

 * @param lpEventAttributes 设定事件的安全属性,NULL表示是用默认属性。
 * @param bManualReset 人工重置事件(TRUE),自动重置事件(FALSE)。
 * @param bInitialState 事件初始化为有信号(TRUE),或无信号(FALSE)。
 * @param lpName 命名事件对象名字或未命名(NULL)。
 
*/

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
                   BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName);

该函数可以用来创建一个事件对象,也可以用来打开一个已存在的事件对象句柄。在函数调用后立即调用GetLastError()函数,如果返回是ERROR_ALREADY_EXISTS,则说明调用打开一个现有的事件。

      打开已存在事件对象的句柄还可以调用以下原型:

/*! 参数含义同OpenMutex的参数. */
HANDLE OpenEvent(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);

        关闭事件对象,调用CloseHandle()函数。用户必须为每个CreateEvent()或OpenEvent()函数调用一个CloseHandle()函数。

        为了将事件对象设置为有信号状态,调用SetEvent()和PulseEvent()函数,这两个函数分别描述如下:

BOOL SetEvent(HANDLE hEvent);
BOOL PulseEvent(HANDLE hEvent);

        这两个函数都接受一个事件对象的句柄。SetEvent()函数并不将事件重置为无信号状态,对自动重置事件,SetEvent()只解锁一个在该事件上等待的线程。,WaitForSingleObject()或其他等待函数自动将事件重置为无信号状态。对人工重置事件,SetEvent()解锁在该事件上等待的所有线程,即当人工重置事件变为有信号后,所有等待该事件的线程都被允许运行了,它将保持有信号状态,直到某个线程显式地重置该事件。

        PulseEvent()将事件标识为有信号状态并重置事件,它相当于连续执行3步骤:调用SetEvent()、释放等待事件、在立即调用ResetEvent()函数。当PulseEvent()返回时,时间仍留在无信号状态。对人工重置事件,PulseEvent()解锁在事件上等待的所有线程。对自动事件,PulseEvent()只解锁一个线程。

        要显式(人工)地重置一个事件,调用如下函数:

/* Brief 重置一个事件对象。

 * 该函数能将指定事件对象重置为无信号状态。
 
*/

BOOL ResetEvent(HANDLE hEvent);
        单线程能在几个同时的操作中定义不同的事件对象。如果是这种情况,用一个多对象等待函数来等待将被标识的任何事件对象的状态。也能用事件对象在许多情况下通知一个正在等待的线程一个事件的发生。这段话说得是一个问题的两种解决办法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值