windows多线程程序设计(基础篇)

基础篇包括了4个小内容。

1.基本的线程操作

2.线程对象封装

3.互斥和临界区

4.同步操作


1.基本的线程操作

线程函数

  win32 c
创建线程 CreateThread

_beginthread

_beginthreadex

恢复线程

ResumeThread  

挂起线程

SuspendThread  

退出线程

ExitThread

_endthread

_endthreadex

强制结束线程

TerminateThread  

释放线程对象

CloseHandle  
设置线程优先级 SetThreadPriority  

线程回调函数

ThreadProc  

Demo1

#include 
#include 
#include 
unsigned __stdcall MyThreadFunc(void* p)
{
	printf("线程启动,停留3秒\n");
	Sleep(3000);
	printf("线程退出\n");
	_endthreadex(0);				// c语言退出线程函数
	return 0;
}

int main()
{
	HANDLE hThread;
	unsigned threadID;

	hThread = (HANDLE)_beginthreadex(		// c语言创建线程函数
		NULL,					// 安全属性
		0,					// 线程堆栈大小
		&MyThreadFunc,				// 函数指针,指向线程函数
		NULL,					// 函数参数,输入到线程函数
		0,					// 新线程的初始状态,0表示立即执行,CREATE_SUSPENDED 表示创建之后挂起
		&threadID);				// 返回线程ID

	DWORD dw = WaitForSingleObject(hThread,		// 资源句柄, 这里是线程的句柄
		INFINITE);				// INFINITE-无线等待	数字-等待时长(毫秒)
	switch (dw)					// 返回值
	{
	case WAIT_OBJECT_0:
		// 等到第0个对象
		break;
	case WAIT_TIMEOUT:
		// 等待超时
		break;
	case WAIT_FAILED:
		// 输入句柄错误
		break;
	}
	CloseHandle(hThread);

	system("Pause");
    return 0;
}

2.线程对象封装

通过封装可以定义自己的线程类

Demo2

#include 
#include 

DWORD WINAPI ThreadFunWrapper(LPVOID lpParam);
class MyThread
{
public:
	HANDLE hSendthread;
	MyThread(void);
	~MyThread(void);
	void StartThread();
	void StopThread();
	void ThreadFun();
};
MyThread::MyThread(void) // 创建线程
{
	hSendthread = CreateThread(0, 
		0,
		ThreadFunWrapper,			// ThreadFun()是类成员函数,createthread不能接受成员函数的指针,所以需要创建一个封装函数。
		this,					// 实例指针,传递给封装函数
		CREATE_SUSPENDED,		
		0);			
};

MyThread::~MyThread(void)  
{
	TerminateThread(hSendthread, 0);	        // 强制删除线程
	CloseHandle(hSendthread);
};

void MyThread::StartThread()
{
	ResumeThread(hSendthread);
};

void MyThread::StopThread()
{
	SuspendThread(hSendthread);
};

void MyThread::ThreadFun()
{
	printf("线程启动,停留3秒\n");
	Sleep(3000);
	printf("线程退出\n");
	ExitThread(0);					// windows api线程结束函数
};

DWORD WINAPI ThreadFunWrapper(LPVOID lpParam)		// 封装函数
{
	MyThread * pMyThread =
		reinterpret_cast(lpParam);
	pMyThread->ThreadFun();
	return 0;
}

int main()
{
	MyThread tr;					// 默认创建的线程是挂起状态
	tr.StartThread();				// 从挂起状态恢复
	WaitForSingleObject(tr.hSendthread,10000);	// 等待线程退出
	system("Pause");
    return 0;
}

3.互斥和临界区

  互斥 临界区
类型

HANDLE   hMutex 

CRITICAL_SECTION g_cs;

创建

CreateMutex

InitializeCriticalSection(&g_cs);

释放

CloseHandle

DeleteCriticalSection(&g_cs);

进入lock

WaitForSingleObject

WaitForMultipleObjects

EnterCriticalSection(&g_cs);

离开unlock

ReleaseMutex

LeaveCriticalSection(&g_cs);

Mutex可以和waitfor系列函数搭配使用,且支持跨进程,功能强大。CriticalSection容易理解使用较为简单。

demo3

#include 
#include 
#include 

CRITICAL_SECTION g_cs;

unsigned __stdcall MyThreadFunc(void* pArguments)
{
	// EnterCriticalSection(&g_cs);			// 进入临界区
	for (int i = 0; i < 100; i++)
		putchar('0' + *(int*)pArguments);
	putchar('\n');
	// LeaveCriticalSection(&g_cs);			// 退出临界区
	_endthreadex(0);							
	return 0;
}

int main()
{
	HANDLE hThread[5];
	unsigned threadID[5];
	int id[5] = { 1, 2, 3, 4, 5 };
	InitializeCriticalSection(&g_cs);

	int i;
	for (i = 0; i < 5; i++)
		hThread[i] = (HANDLE)_beginthreadex(NULL, 0, &MyThreadFunc, &id[i], 0, &threadID[i]);
		
	DWORD dw = WaitForMultipleObjects(		// 等所有线程完成工作
		5,					// 等待事件的总数量
		hThread,				// 事件数组
		TRUE,					// TRUE-等待全部事件 FALSE-等待任一事件
		10000);					// 最长等待多长事件
	switch (dw)					// 处理返回值
	{
	case WAIT_OBJECT_0 + 0:
		break;
	case WAIT_OBJECT_0 + 1:
		break;
	case WAIT_OBJECT_0 + 2:
		break;
	case WAIT_OBJECT_0 + 3:
		break;
	case WAIT_OBJECT_0 + 4:
		break;
	case WAIT_TIMEOUT:
		break;
	case WAIT_FAILED:
		break;
	default:
		break;
	}

	for (i = 0; i < 5; i++)		// 释放所有线程句柄
		CloseHandle(hThread[i]);

	DeleteCriticalSection(&g_cs);
	system("Pause");
    return 0;
}

4.同步操作

  信号量 事件
初始化 CreateSemaphore CreateEvent

获取访问权

OpenSemaphore OpenEvent

P操作

WaitForSingleObject

WaitForMultipleObjects

WaitForSingleObject

WaitForMultipleObjects

V操作

ReleaseSemaphore SetEvent

信号量支持多个资源,类似操作系统中的记录型信号量,可用于多个同类型资源管理。event事件主要用于实现操作同步。

Demo4同步

下例中有两组同步关系,停车|开门,关门|开车。用两个event分别表示。

加入PV操作后可得,停车V(s1)|P(s1)开门,关门V(s2)|P(s2)开车。

#include 
#include 

HANDLE hevent1, hevent2;
HANDLE hevent_exit;
DWORD WINAPI SellerThreadFunc(void* p);
DWORD WINAPI DriverThreadFunc(void* p);

int main()
{
	CreateMutex(NULL, FALSE, NULL);
	srand(342443);
	DWORD sellerthreadid, driverthreadid;
	// CreateEvent函数说明
	// 参数2 指定将事件对象创建成手动复原还是自动复原。FALSE-自动复位,当一个等待线程(WaitForSingleObject)被释放以后自动将事件状态复位到无信号状态。TRUE - 人工复位,调用ResetEvent函数将事件的状态复位到无信号状态。
	// 参数3 指定事件对象的初始状态。TRUE-初始状态为有信号状态;FALSE-初始状态为无信号状态。
	hevent1 = CreateEvent(NULL, TRUE, FALSE, _T("s1"));	// event对象为人工复位模式
	hevent2 = CreateEvent(NULL, FALSE, FALSE, _T("s2"));	// event对象为自动复位模式
	hevent_exit = CreateEvent(NULL, TRUE, FALSE, _T("ext"));// 人工复位的事件,初始状态为有信号状态

	HANDLE h[2];
	h[0] = CreateThread(0, 0, SellerThreadFunc, NULL, 0, &sellerthreadid);
	h[1] = CreateThread(0, 0, DriverThreadFunc, NULL, 0, &driverthreadid);

	Sleep(10000);						// 20秒后发送结束信号
	SetEvent(hevent_exit);				        // 人工复位的事件,初始状态为有信号状态
	WaitForMultipleObjects(2, h, TRUE, INFINITE);		// 等待所有线程退出
	CloseHandle(hevent1);
	CloseHandle(hevent2);
	CloseHandle(hevent_exit);
	CloseHandle(h[0]);
	CloseHandle(h[1]);
	system("Pause");
    return 0;
}

DWORD WINAPI SellerThreadFunc(void* p)
{
	while (1)
	{
		Sleep(rand() % 1000);
		printf("售票员: 关门 V(s2)\n");
		SetEvent(hevent1);
		Sleep(rand() % 1000);
		printf("售票员: 售票\n");
		Sleep(rand() % 1000);				// 随机等待0~999毫秒
		WaitForSingleObject(hevent2, INFINITE);
		printf("售票员: 开门 P(s1)\n");

		DWORD dw = WaitForSingleObject(hevent_exit, 0);	// 检测结束事件,不等待。
		if (dw == WAIT_OBJECT_0)		        // 如果是结束事件则退出线程。
			ExitThread(0);
	}
}
DWORD WINAPI DriverThreadFunc(void* p)
{
	while (1)
	{
		WaitForSingleObject(hevent1, INFINITE);
		ResetEvent(hevent1);				// event对象为人工复位模式
		Sleep(rand() % 1000);
		printf("司  机: 开车 P(s2)\n");
		Sleep(rand() % 1000);
		printf("司  机: 驾驶\n");
		Sleep(rand() % 1000);
		printf("司  机: 停车 V(s1)\n");
		SetEvent(hevent2);

		DWORD dw = WaitForSingleObject(hevent_exit, 0);
		if (dw == WAIT_OBJECT_0)
			ExitThread(0);
	}
}

 

你可能感兴趣的:(多线程程序设计,多线程,同步,互斥,信号量,windows)