多线程(9)多线程同步之事件对象(windows实现)
1. 事件(对象)的概念:
事件是内核对象,多用于线程间通信,可以跨进程同步,用于一个线程来唤醒另一个线程(包括自动和人工两种方式)。
2.接口函数
2.1 创建事件-CreateEvent
2.1 原型
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,// 安全属性
BOOLbManualReset,// 复位方式
BOOLbInitialState, // initial state初始状态
LPCTSTRlpName // 对象名称
);
2.2 说明
调用过程中的任何线程,都可以在一个等待函数中指定事件对象句柄。
当指定的对象的状态为有信号时,单对象等待函数(例如WaitForSingleObject)返回
2.3 参数-bManualReset
一、 bManualReset:
指定将创建的EVENT是自动复位还是手动复位。
- 如果为TRUE,需要用 ResetEvent(HANDLE)函数手动复位状态为无信号,即一旦改EVENT被设置成有信号,则它会一直等到ResetEvent调用时才为无信号状态。
- 如果为FALSE,当一个有信号的等待线程被释放后,系统会自动复位状态为无信号状态。
二、bInitialState:
指定事件对象的初始状态。
如果为TRUE,初始状态为有信号,否则为无信号。
2.4 举例子:
-
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//线程释放后自动重置为无信号状态,初始化时为无信号状态
因为初始为无信号状态,所以hEvent一直处于无信号状态,
因此这线程一直在等待,直到主线程结束。 -
hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
使用手动重置为无信号状态,初始化时有信号状态
所以hEvent一直处于有信号状态,无论是线程1释放后,hEvent仍处于有信号状态,所以线程2正常执行了。
2.1 设置信号状态-SetEvent
SetEvent(hEvent))//设置信号为有信号状态
ResetEvent,这个函数把指定的事件对象设置为无信号状态。
3.代码例子
HANDLE hEvent,hEventOne,hEventTwo;
DWORD WINAPI eventThreadOne(LPVOID lp)
{
cout<<"-----in eventThread One-----"<<endl;
DWORD res =WaitForSingleObject(hEvent,INFINITE);
if (WAIT_OBJECT_0 == res)
{
cout<<"eventThread One wait event"<<endl;
}
if(!SetEvent(hEvent))//场景2 4 置为有信号 BOOL SetEvent(HANDLE hEvent);
{
cout<<"set event fail"<<endl;
}
return 0;
}
DWORD WINAPI eventThreadTwo(LPVOID lp)
{
cout<<"-----in eventThread Two-----"<<endl;
DWORD res =WaitForSingleObject(hEvent,INFINITE);
if (WAIT_OBJECT_0 == res)
{
cout<<"eventThread Two wait event"<<endl;
}
return 0;
}
void eventTest()
{
//hEvent=CreateEvent(NULL,true,true,NULL);//场景1. 手动置为有信号,初始化为有信号 都运行
//hEvent=CreateEvent(NULL,false,true,NULL); //场景2. 手动置为无信号,初始化为有信号 只有一个运行
//hEvent=CreateEvent(NULL,true,false,NULL); //场景3. 手动置为有信号,初始化为无信号 都不运行,只有reset有信号才运行 SetEvent(hEvent)
hEvent=CreateEvent(NULL,false,false,NULL);//场景4. 手动置为无信号,初始化为无信号 都不运行,只有reset有信号才运行一个线程,
if(!SetEvent(hEvent))//场景3,4 置为有信号 BOOL SetEvent(HANDLE hEvent);
{
cout<<"set event fail"<<endl;
}
if (!hEvent)
{
cout<<"create event failed"<<endl;
return ;
}
hEventOne=CreateThread(0,0,eventThreadOne,0,0,0);
Sleep(200);
hEventTwo=CreateThread(0,0,eventThreadTwo,0,0,0);
WaitForSingleObject(hEventOne,INFINITE);
WaitForSingleObject(hEventTwo,INFINITE);
CloseHandle(hEventTwo);
CloseHandle(hEventOne);
CloseHandle(hEvent);
return;
}
4. TJ代码实现 以vad为例
主线程:
定义:
typedef HANDLE VAThread_cond_t;
VAThread_cond_t m_hCond;
创建事件对象
VAThreadCondInit(&m_hCond))
CreateEvent(NULL, FALSE, FALSE, NULL);//手动置为无信号,初始化为无信号
设置为有信号
VAThreadSetSignal(&m_hCond);
SetEvent(*cond)
执行线程:
先置为无信号,然后等待信号到来
VAThreadCondTimedWait(&m_hCond, &m_hMutex, 100)
ResetEvent(*cond);
ret = WaitForSingleObject(*cond, millisecond);