Thread synchronization of windows core programming



Source: WeChat Official Account "Programming Learning Base"

Thread synchronization

What happens if the threads are not synchronized?

#include <stdio.h>
#include <windows.h>

static int count = 20;
const unsigned int MAX = 4;
// 线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    
    
	while (count >= 0)
	{
    
    
		printf("coutn:%d \tThread:%d\n", count--, GetCurrentThreadId());
	}
	return 0;
}

int  main(int argc, char* argv[])
{
    
    
	HANDLE hThread[MAX];
	DWORD dwThreadId;

	// 创建一个线程
	hThread[0] = CreateThread(
		NULL,		// 默认安全属性
		NULL,		// 默认堆栈大小
		ThreadProc,	// 线程入口地址(执行线程的函数)
		NULL,		// 传给函数的参数
		0,		// 指定线程立即运行
		&dwThreadId);	// 返回线程的ID号
	hThread[1] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[2] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[3] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);

	// 等待新线程运行结束
	WaitForMultipleObjects(MAX, hThread, true, INFINITE);	//一直等待,直到所有子线程全部返回
	for (int i = 0; i < MAX; i++)
	{
    
    
		CloseHandle(hThread[i]);
	}
	return 0;
}

operation result:

coutn:20        Thread:9104
coutn:18        Thread:9104
coutn:17        Thread:9104
coutn:15        Thread:14248
coutn:13        Thread:14248
coutn:16        Thread:10472
coutn:11        Thread:10472
coutn:10        Thread:10472
coutn:9         Thread:10472
coutn:8         Thread:10472
coutn:7         Thread:10472
coutn:6         Thread:10472
coutn:5         Thread:10472
coutn:4         Thread:10472
coutn:3         Thread:10472
coutn:2         Thread:10472
coutn:1         Thread:10472
coutn:0         Thread:10472
coutn:14        Thread:9104
coutn:19        Thread:3076
coutn:12        Thread:14248

Critical section

The critical section object is a CRITICAL_SECTION structure defined in the data segment. Some information is recorded through this structure so that only one thread can access the data in the data segment at the same time.

CRITICAL_SECTION是不能够“锁定”资源的,它能够完成的功能,是同步不同线程的代码段。

Initialize critical section objects

void InitializeCriticalSection(
  LPCRITICAL_SECTION lpCriticalSection
);

Enter and leave the critical zone

void EnterCriticalSection(
  LPCRITICAL_SECTION lpCriticalSection
);
void LeaveCriticalSection(
  LPCRITICAL_SECTION lpCriticalSection
);

Delete critical section objects

void DeleteCriticalSection(
  LPCRITICAL_SECTION lpCriticalSection
);

Usage example

#include <stdio.h>
#include <windows.h>

static int count = 20;
const unsigned int MAX = 4;
CRITICAL_SECTION g_cs;		//对存在同步问题的代码段使用临界区对象
// 线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    
    
	while (count >= 0)
	{
    
    
		EnterCriticalSection(&g_cs);
		printf("coutn:%d \tThread:%d\n", count--, GetCurrentThreadId());
		LeaveCriticalSection(&g_cs);
		Sleep(1);
	}
	return 0;
}

int  main(int argc, char* argv[])
{
    
    
	HANDLE hThread[MAX];
	DWORD dwThreadId;

	// 初始化临界区对象
	InitializeCriticalSection(&g_cs);

	// 创建一个线程
	hThread[0] = CreateThread(
		NULL,		// 默认安全属性
		NULL,		// 默认堆栈大小
		ThreadProc,	// 线程入口地址(执行线程的函数)
		NULL,		// 传给函数的参数
		0,		// 指定线程立即运行
		&dwThreadId);	// 返回线程的ID号
	hThread[1] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[2] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[3] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);

	// 等待新线程运行结束
	WaitForMultipleObjects(MAX, hThread, true, INFINITE);	//一直等待,直到所有子线程全部返回
	for (int i = 0; i < MAX; i++)
	{
    
    
		CloseHandle(hThread[i]);
	}
	// 删除临界区对象
	DeleteCriticalSection(&g_cs);
	return 0;
}

Output

coutn:20        Thread:5340
coutn:19        Thread:5808
coutn:18        Thread:3884
coutn:17        Thread:5340
coutn:16        Thread:1772
coutn:15        Thread:1772
coutn:14        Thread:5340
coutn:13        Thread:3884
coutn:12        Thread:5808
coutn:11        Thread:3884
coutn:10        Thread:5340
coutn:9         Thread:1772
coutn:8         Thread:5808
coutn:7         Thread:3884
coutn:6         Thread:5340
coutn:5         Thread:1772
coutn:4         Thread:5808
coutn:3         Thread:1772
coutn:2         Thread:3884
coutn:1         Thread:5808
coutn:0         Thread:5340

Mutually Exclusive Function

LONG InterlockedDecrement(
  LONG volatile *Addend		//指向递减的变量
);
LONG InterlockedIncrement(
  LONG volatile *Addend		//指向递增的变量
);
#include <stdio.h>
#include <windows.h>

static int count = 20;
const unsigned int MAX = 4;
// 线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    
    
	while(count >= 0)
	{
    
    
		InterlockedDecrement((long*)&count);
		printf("coutn:%d \tThread:%d\n", count, GetCurrentThreadId());
		Sleep(10);
	}
	return 0;
}

int main(int argc, char* argv[])
{
    
    
	HANDLE hThread[MAX];
	DWORD dwThreadId;

	// 创建一个线程
	hThread[0] = CreateThread(
		NULL,		// 默认安全属性
		NULL,		// 默认堆栈大小
		ThreadProc,	// 线程入口地址(执行线程的函数)
		NULL,		// 传给函数的参数
		0,		// 指定线程立即运行
		&dwThreadId);	// 返回线程的ID号
	hThread[1] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[2] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[3] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);

	// 等待新线程运行结束
	WaitForMultipleObjects(MAX, hThread, true, INFINITE);	//一直等待,直到所有子线程全部返回
	for (int i = 0; i < MAX; i++)
	{
    
    
		CloseHandle(hThread[i]);
	}
	return 0;
}

Event kernel object

The event kernel object is an abstract object. It has two states: trusted and untrusted, and WaitForSingleObjectthread synchronization is realized by waiting.

HANDLE CreateEventA(
  LPSECURITY_ATTRIBUTES lpEventAttributes,	//安全属性
  BOOL                  bManualReset,		//是否手动重置事件对象为未受信对象
  BOOL                  bInitialState,		//指定事件对象创建时的初始状态
  LPCSTR                lpName				//事件对象的名称
);

Set kernel object state

BOOL SetEvent(
  HANDLE hEvent
);
BOOL ResetEvent(
  HANDLE hEvent
);

Wait for the event kernel object to be trusted

DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD  dwMilliseconds
);

Example:

#include <stdio.h>
#include <windows.h>

static int count = 20;
const unsigned int MAX = 4;
HANDLE g_hEvent;
// 线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    
    
	while (count >= 0)
	{
    
    
		/*等待内核对象受信,函数调用结束内核对象被设置为未授信*/
		WaitForSingleObject(g_hEvent, INFINITE);
		printf("coutn:%d \tThread:%d\n", count--, GetCurrentThreadId());
		SetEvent(g_hEvent);				/*设置受信*/
		Sleep(10);
	}
	return 0;
}

int  main(int argc, char* argv[])
{
    
    
	HANDLE hThread[MAX];
	DWORD dwThreadId;

	// 创建一个自动重置的(auto-reset events),受信的(signaled)事件内核对象
	g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);

	// 创建一个线程
	hThread[0] = CreateThread(
		NULL,		// 默认安全属性
		NULL,		// 默认堆栈大小
		ThreadProc,	// 线程入口地址(执行线程的函数)
		NULL,		// 传给函数的参数
		0,		// 指定线程立即运行
		&dwThreadId);	// 返回线程的ID号
	hThread[1] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[2] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);
	hThread[3] = CreateThread(NULL, NULL, ThreadProc, NULL, 0, &dwThreadId);

	// 等待新线程运行结束
	WaitForMultipleObjects(MAX, hThread, true, INFINITE);	//一直等待,直到所有子线程全部返回
	for (int i = 0; i < MAX; i++)
	{
    
    
		CloseHandle(hThread[i]);
	}
	return 0;
}

Output

coutn:20        Thread:3156
coutn:19        Thread:9360
coutn:18        Thread:11444
coutn:17        Thread:17128
coutn:16        Thread:3156
coutn:15        Thread:9360
coutn:14        Thread:11444
coutn:13        Thread:17128
coutn:12        Thread:3156
coutn:11        Thread:17128
coutn:10        Thread:9360
coutn:9         Thread:11444
coutn:8         Thread:3156
coutn:7         Thread:17128
coutn:6         Thread:9360
coutn:5         Thread:11444
coutn:4         Thread:3156
coutn:3         Thread:11444
coutn:2         Thread:9360
coutn:1         Thread:17128
coutn:0         Thread:3156

Guess you like

Origin blog.csdn.net/qq_44519484/article/details/109678961