C++多线程 之 事件

线程同步的方式和机制

临界区、互斥区、事件、信号量四种方式

========================================================

临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别 

1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。

2、互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 

3、信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 

4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作


事件包含的几个操作原语: 

  CreateEvent() 创建一个事件 

  OpenEvent() 打开一个事件 

  SetEvent() 回置事件 

  WaitForSingleObject() 等待一个事件 

  WaitForMultipleObjects()    等待多个事件

示例1:

#include "stdafx.h"
#include <afxmt.h>
#include <process.h>
// typedef unsigned (__stdcall* _beginthreadex_proc_type)(void*);
unsigned __stdcall ThreadA(void* pParam);
HANDLE g_hEvent = NULL;

int main()
{
    //g_hEvent = CreateEvent(nullptr, TRUE,  FALSE, L"My_Event");
    //g_hEvent = CreateEvent(nullptr, TRUE, TRUE, L"My_Event");
    // 创建一个手动重置的无信号事件
    g_hEvent = CreateEvent(nullptr, TRUE, FALSE, L"My_Event");
    // _beginthread  CreateThread
    unsigned uID;
    int n = _beginthreadex(NULL, 0, ThreadA, nullptr, 0, &uID);
    Sleep(1500);
    SetEvent(g_hEvent);
    Sleep(10000);
    return 0;
}

unsigned __stdcall ThreadA(void* pParam)
{
    WaitForSingleObject(g_hEvent, INFINITE);
    printf("ThreadA\n");
    ResetEvent(g_hEvent);
    return 0;
}

示例2: 依次打印ABCABC

#include "stdafx.h"
#include <afxmt.h>
#include <process.h>
unsigned __stdcall ThreadA(void* pParam);
unsigned __stdcall ThreadB(void* pParam);
unsigned __stdcall ThreadC(void* pParam);

HANDLE g_hEvent[3];
int main()
{
	//g_hEvent = CreateEvent(nullptr, TRUE,  FALSE, L"My_Event");
	//g_hEvent = CreateEvent(nullptr, TRUE, TRUE, L"My_Event");
	// 创建一个手动重置的无信号事件
	//g_hEvent = CreateEvent(nullptr, TRUE, FALSE, L"My_Event");
	g_hEvent[0] = CreateEvent(nullptr, FALSE, FALSE, L"My_EventA");
	g_hEvent[1] = CreateEvent(nullptr, FALSE, FALSE, L"My_EventB");
	g_hEvent[2] = CreateEvent(nullptr, FALSE, FALSE, L"My_EventC");
	// _beginthread  CreateThread
	unsigned uID;
	int n = _beginthreadex(NULL, 0, ThreadA, nullptr, 0, &uID);
	int m = _beginthreadex(NULL, 0, ThreadB, nullptr, 0, &uID);
	int w = _beginthreadex(NULL, 0, ThreadC, nullptr, 0, &uID);
	SetEvent(g_hEvent[2]);
	//Sleep(1500);
	//SetEvent(g_hEvent);
	Sleep(INFINITE);
	return 0;
}

unsigned __stdcall ThreadA(void* pParam)
{
	while (true)
	{
		WaitForSingleObject(g_hEvent[0], INFINITE);
		printf("A \n");
		Sleep(500);
		SetEvent(g_hEvent[1]);
	}
	return 0;
}

unsigned __stdcall ThreadB(void* pParam)
{
	while (true)
	{
		WaitForSingleObject(g_hEvent[1], INFINITE);
		printf("--B --------------------------------------\n\n");
		Sleep(500);
		SetEvent(g_hEvent[2]);
	}
	return 0;
}

unsigned __stdcall ThreadC(void* pParam)
{
	while (true)
	{
		WaitForSingleObject(g_hEvent[2], INFINITE);
		printf("----C \n");
		Sleep(500);
		SetEvent(g_hEvent[0]);
	}
	return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注