利用事件对象实现线程同步

来源:互联网 发布:淘宝差评被骚扰怎么办 编辑:程序博客网 时间:2024/05/16 08:42

        事件对象也属于内核对象,允许任意数目的线程对资源拥有同步访问的权限,该对象包含:使用计数、指示人工重置事件/自动重置事件的布尔值、通知状态的布尔值。事件对象包含人工重置事件对象和自动重置事件对象。

        人工重置事件对象:当该对象得到通知时,等待该对象的所有线程均变为可调度线程。并且需要调用ResetEvent函数手动设置事件对象为无信号状态。

        自动重置事件对象:当该对象得到通知时,等待该对象的所有线程,只有一个变为可调度线程。系统会自动设置该对象为无信号状态,当代码的保护执行完之后要调用SetEvent函数,将其设置为有信号。

        创建事件对象的函数原型如下:

CreateEvent(LPSECURITY_ATTRIBUTES  lpEventAttributes,BOOL  bManualReset,BOOL  bInitialState,LPCTSTR  lpName);
bManualReset:指明是人工重置事件对象还是自动重置时间对象。

bInitialState:     指定对象的初始状态,有信号还是无信号。

        另外两个函数,SetEvent、ResetEvent为把指定对象设置为有信号状态、无信号状态。关于线程同步的例子如下:

#include <windows.h>#include <iostream>DWORD WINAPI Fun1Proc(LPVOID lpParameter);DWORD WINAPI Fun2Proc(LPVOID lpParameter);int index = 0;int tickets = 100;HANDLE hEvent;int main(){    HANDLE hThread1;    HANDLE hThread2;     //创建事件对象hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);    if(hEvent)    {        if (ERROR_ALREADY_EXISTS == GetLastError())        {            std::cout << "only one instance can run!" << std::endl;            return 0;        }    }     //创建线程    hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);    hThread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL);        CloseHandle(hThread1);       CloseHandle(hThread2);    Sleep(4000);    std::cout<< "now is the main thread in running\n";CloseHandle(hEvent);system("pause");    return 0;}//线程1的入口函数DWORD WINAPI Fun1Proc(LPVOID lpParameter){    while (true)    {                WaitForSingleObject(hEvent, INFINITE);        if (tickets>0)        {            Sleep(1);             std::cout << "thread1 sell ticket :" << tickets-- << std::endl;SetEvent(hEvent);        }        else{SetEvent(hEvent);            break;}    }     return 0;}//线程2的入口函数DWORD WINAPI Fun2Proc(LPVOID lpParameter){    while (true)    {              WaitForSingleObject(hEvent,INFINITE);        if (tickets>0)        {            Sleep(1);            std::cout << "thread2 sell ticket :" << tickets-- << std::endl;SetEvent(hEvent);        }else{SetEvent(hEvent);            break;}    }        return 0;}


一般情况下,为了实现线程间的同步,我们不使用人工重置事件对象,而是使用自动重置事件对象,并在初始时,将其设置为有信号状态。

0 0
原创粉丝点击