MFC(学习笔记) - 多线程同步

一、win32线程创建与互斥

创建线程

HANDLE WINAPI CreateThread(
  _In_opt_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  _In_      SIZE_T                 dwStackSize,
  _In_      LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_  LPVOID                 lpParameter,
  _In_      DWORD                  dwCreationFlags,
  _Out_opt_ LPDWORD                lpThreadId
);

参数介绍

1、线程安全属性,一般为NULL

2、线程栈大小:一般为0,取默认大小

3、线程的函数名:顾名思义,如果为类内的函数,则设为static即可

4、线程的参数:可以传递一个结构体指针,没有则为NULL

5、创建的标记:一般设为0

6、线程的ID:如非必须,设为NULL

互斥锁

HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,
  _In_opt_ LPCTSTR               lpName
);

参数介绍

1、互斥锁安全属性:一般为NULL

2、互斥锁默认是否有信号:一般为FALSE,表示无人拥有此信号,TRUE表示信号已被人拥有,不可再获取

3、互斥锁名称:一般为NULL,由于此锁为内核对象,进程间互斥的话,需要命名

注:互斥锁,谁拥有,谁释放;多次拥有,需要多次释放;谁创建时,参数为TRUE,谁拥有;

卖票例子

int ticket = 10;
HANDLE hMutex;

DWORD WINAPI Thread1(LPVOID param) {
	while (TRUE)
	{
		WaitForSingleObject(hMutex, INFINITE);
		Sleep(500);
		if (ticket > 0)
			cout << "线程1:" << ticket-- << endl;
		else
			break;
		ReleaseMutex(hMutex);
		
	}
	return TRUE;
}
DWORD WINAPI Thread2(LPVOID param) {
	while (TRUE)
	{
		WaitForSingleObject(hMutex, INFINITE);
		Sleep(500);
		if (ticket > 0)
			cout << "线程2:" << ticket-- << endl;
		else
			break;
		ReleaseMutex(hMutex);
	}
	return TRUE;
}
int main()
{
	HANDLE hTread1 = CreateThread(NULL, 0, Thread1, NULL,0, NULL);
	HANDLE hTread2 = CreateThread(NULL, 0, Thread2, NULL,0, NULL);
	CloseHandle(hTread1);
	CloseHandle(hTread2);
	hMutex = CreateMutex(NULL, FALSE, NULL);
	getchar();
	return 0;
}

注:MFC中封装了CMutex类

#include "afxmt.h"
CMutex mt;
mt.Lock();
mt.Unlock();

二、内核对象——事件

HANDLE WINAPI CreateEvent(
  _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
  _In_     BOOL                  bManualReset,
  _In_     BOOL                  bInitialState,
  _In_opt_ LPCTSTR               lpName
);


参数介绍:

1、事件安全属性:一般为NULL,即默认

2、是否人工重置:TRUE代表由人工重置为初始信号,FALSE代表自动重置为初始信号

3、事件的初始信号:TRUE表示有信号,FALSE表示无信号

4、事件的名称:与上面的mutex一样

同样的卖票例子

// ThreadTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

int ticket = 10;
HANDLE hEvent;

DWORD WINAPI Thread1(LPVOID param) {
	while (TRUE)
	{
		WaitForSingleObject(hEvent, INFINITE);
		Sleep(500);
		if (ticket > 0)
			cout << "线程1:" << ticket-- << endl;
		else
			break;
		SetEvent(hEvent);

	}
	return TRUE;
}
DWORD WINAPI Thread2(LPVOID param) {
	while (TRUE)
	{
		WaitForSingleObject(hEvent, INFINITE);
		Sleep(500);
		if (ticket > 0)
			cout << "线程2:" << ticket-- << endl;
		else
			break;
		SetEvent(hEvent);
	}
	return TRUE;
}
int main()
{
	HANDLE hTread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
	HANDLE hTread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);
	CloseHandle(hTread1);
	CloseHandle(hTread2);
	hEvent = CreateEvent(NULL,FALSE, FALSE, NULL);
	SetEvent(hEvent);
	getchar();
	return 0;
}

三、临界区

一共四个函数

void WINAPI InitializeCriticalSection(
  _Out_ LPCRITICAL_SECTION lpCriticalSection
);

void WINAPI EnterCriticalSection(
  _Inout_ LPCRITICAL_SECTION lpCriticalSection
);


void WINAPI LeaveCriticalSection(
  _Inout_ LPCRITICAL_SECTION lpCriticalSection
);


void WINAPI DeleteCriticalSection(
  _Inout_ LPCRITICAL_SECTION lpCriticalSection
);

卖票的例子

// ThreadTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

int ticket = 10;
CRITICAL_SECTION g_cs;

DWORD WINAPI Thread1(LPVOID param) {
	while (TRUE)
	{
		EnterCriticalSection(&g_cs);
		if (ticket > 0)
			cout << "线程1:" << ticket-- << endl;
		else
			break;
		LeaveCriticalSection(&g_cs);
		Sleep(500);
	}
	return TRUE;
}
DWORD WINAPI Thread2(LPVOID param) {
	while (TRUE)
	{
		EnterCriticalSection(&g_cs);
		if (ticket > 0)
			cout << "线程2:" << ticket-- << endl;
		else
			break;
		LeaveCriticalSection(&g_cs);
		Sleep(500);
	}
	return TRUE;
}
int main()
{
	HANDLE hTread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
	HANDLE hTread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);
	CloseHandle(hTread1);
	CloseHandle(hTread2);
	InitializeCriticalSection(&g_cs);
	getchar();
	DeleteCriticalSection(&g_cs);
	return 0;
}

注:c++封装好的临界区类critical_section,简单好用如下:

#include "concrt.h"
using namespace concurrency;
critical_section g_cs;
g_cs.lock();
g_cs.unlock();















你可能感兴趣的:(MFC(学习笔记) - 多线程同步)