用内核对象进行线程同步——事件内核对象

事件内核对象
1. 手动重置事件:当一个手动重置事件被触发的时候,所有等待该事件的线程都变为可调度状态。所以要注意此时所有的线程都只能以只读的方式来访问内存,这也是多个线程能够同时运行的唯一原因
2. 自动重置事件:当一个自动重置事件被触发的时候,只有一个等待该事件的线程都变为可调度状态(当线程成功等到事件触发的时候,会自动的把事件重置为未触发状态),其余的继续等待。

创建一个事件内核对象

HANDLE CreateEvent(
     LPSECURITY_ATTRIBUTES lpEventAttributes,
     BOOL bManualReset,  //TRUE:手动重置事件; FALSE:自动重置事件
     BOOL bInitialState, //TRUE:事件初始化为触发状态; FALSE:事件初始化为未触发状态
     LPCSTR lpName
    );

打开一个事件内核对象
其他进程中的线程要访问该事件对象可以调用OpenEvent

HANDLE OpenEvent(
     DWORD dwDesiredAccess,
     BOOL bInheritHandle,
     LPCSTR lpName
    );

改变事件触发状态

BOOL SetEvent(HANDLE hEvent);    // 把事件变为触发状态
BOOL ResetEvent(HANDLE hEvent);  // 把事件变为未触发状态

关闭事件对象
当不在需要事件对象时,要调用CloseHandle来将它关闭

BOOL CloseHandle(HANDLE hObject);

手动重置事件例子

#include "stdafx.h"
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

int g_x = 0;
HANDLE g_hEvent;

// 线程只读
UINT WINAPI ThreadFunc1(PVOID pArguments)
{
    WaitForSingleObject(g_hEvent, INFINITE);
    cout << "ThreadFunc1.." << endl;
    _endthreadex(0);
    return 0;
}
// 线程只读
UINT WINAPI ThreadFunc2(PVOID pArguments)
{
    WaitForSingleObject(g_hEvent, INFINITE);
    cout << "ThreadFunc2.." << endl;
    _endthreadex(0);
    return 0;
}
// 线程只读
UINT WINAPI ThreadFunc3(PVOID pArguments)
{
    WaitForSingleObject(g_hEvent, INFINITE);
    cout << "ThreadFunc3.." << endl;
    _endthreadex(0);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE   handle[3];
    unsigned    unThreadID[3];

    cout << "g_x initial value: " << g_x << endl;
    // 创建一个未触发的手动重置事件
    g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    handle[0] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc1,
        NULL,
        0,
        &unThreadID[0]);
    handle[1] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc2,
        NULL,
        0,
        &unThreadID[1]);
    handle[2] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc3,
        NULL,
        0,
        &unThreadID[2]);

    g_x = 100;
    // 给g_x赋值后调用SetEvent触发事件,此时三个线程都变成可调度状态,获得CPU时间。
    // 但是注意此时所有的三个线程都只能以只读的方式来访问内存,这也是三个线程能够同时运行的唯一原因
    SetEvent(g_hEvent);
    WaitForMultipleObjects(3, handle, TRUE, INFINITE);
    CloseHandle(g_hEvent);
    g_hEvent = NULL;
    cout << "g_x Final value: " << g_x << endl;
    getchar();
    return 0;
}

自动重置事件例子

// ThreadDemo.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <windows.h>          
#include <process.h> 
#include <iostream>

using namespace std;

int g_x = 0;
HANDLE g_hEvent;

// 写入线程
UINT WINAPI ThreadFunc1(PVOID pArguments)
{
    // 当线程成功等到事件对象触发的时候,自动重置事件会把事件对象重置为为触发状态,锁定资源,独占内存
    WaitForSingleObject(g_hEvent, INFINITE);
    int n = 0;
    while (n < 5)
    {
        g_x += n;
        n++;
        cout << "ThreadFunc1.." << endl;
    }
    // 当线程结束,要释放资源,故把事件对象重置为触发状态,以便等待该资源的其他线程访问
    SetEvent(g_hEvent);
    _endthreadex(0);
    return 0;
}
// 读线程
UINT WINAPI ThreadFunc2(PVOID pArguments)
{
    WaitForSingleObject(g_hEvent, INFINITE);
    cout << "ThreadFunc2.." << endl;
    SetEvent(g_hEvent);
    _endthreadex(0);
    return 0;
}
// 写入线程
UINT WINAPI ThreadFunc3(PVOID pArguments)
{
    WaitForSingleObject(g_hEvent, INFINITE);
    int n = 0;
    while (n < 5)
    {
        g_x += n;
        n++;
        cout << "ThreadFunc3.." << endl;
    }
    SetEvent(g_hEvent);
    _endthreadex(0);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE   handle[3];
    unsigned    unThreadID[3];

    cout << "g_x initial value: " << g_x << endl;
    // 创建一个未触发的自动动重置事件
    g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    handle[0] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc1,
        NULL,
        0,
        &unThreadID[0]);
    handle[1] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc2,
        NULL,
        0,
        &unThreadID[1]);
    handle[2] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc3,
        NULL,
        0,
        &unThreadID[2]);

    g_x = 100;
    // 由于事件初始化为未触发状态,所以在线程准备完毕后,调用SetEvent触发事件,此时只有一个线程都变成可调度状态,独占资源。其他线程继续等待
    // 由于等待自动重置事件对象的线程是独占资源,故这些线程可读可写
    SetEvent(g_hEvent);
    WaitForMultipleObjects(3, handle, TRUE, INFINITE);
    CloseHandle(g_hEvent);
    g_hEvent = NULL;
    cout << "g_x Final value: " << g_x << endl;
    getchar();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值