Under Windows user mode thread synchronization

Want to synchronize, the only way to know is to actually use thread

Atomic access

Atom is the smallest unit physics, atomic operation is executed by the CPU inside the smallest unit, can no longer be divided

long g_x = 0;
DWORD WINPAI Thread1(LPVOID pvParam)
{
	g_x++;
	return 0;
}
DWORD WINPAI Thread2(LPVOID pvParam)
{
	g_x++;
	return 0;
}

Disassembly:

//Thread1
MOV EAX,[g_x]
INC EAX
MOV [g_x],EAX

//Thread2
MOV EAX,[g_x]
INC EAX
MOV [g_x],EAX

//这样执行没有任何毛病,但是发生如下:
MOV EAX,[g_x]		//Thread1
INC EAX				//Thread1

MOV EAX,[g_x]		//Thread2
INC EAX				//Thread2
MOV [g_x],EAX		//Thread2

MOV [g_x],EAX		//Thread1

//最终两次自增运算,正确结果为2,错误为1
//两个线程发生错乱,导致数据发生错误
//因为++自增运算在C语言看来是原子操作,翻译为汇编后是3次原子操作,所以存在错误

It must be controlled (Interlocked family of functions):
InterlockedExchangeAdd (
PLONG volatile plAddend, // control variable
LONG lIncrement); // change value

long g_x = 0;
DWORD WINPAI Thread1(LPVOID pvParam)
{
	InterlockedExchangeAdd(&g_x,1);
	return 0;
}
DWORD WINPAI Thread2(LPVOID pvParam)
{
	InterlockedExchangeAdd(&g_x,1);
	return 0;
}

//自减时:	InterlockedExchangeAdd(&g_x,-1);

The key segment

The key segment is a small piece of code, it needs exclusive access to some shared resources before execution.
For example: For example, on an airplane, the toilet has a toilet, so the same time allowing only one person (thread) using the toilet (protected resource) in the bathroom (key section). When the toilet is displayed "no", into the toilet labeled "people", after the mark is "no."

CRITICAL_SECTION g_cs;
long g_x = 0;
DWORD WINPAI Thread1(LPVOID pvParam)
{
	EnterCriticalSection(&g_cs);
	g_x ++;
	printf("%d\n",g_x);
	LeaveCriticalSection(&g_cs);
	return 0;
}
DWORD WINPAI Thread2(LPVOID pvParam)
{
	EnterCriticalSection(&g_cs);
	g_x ++;
	printf("%d\n",g_x);
	LeaveCriticalSection(&g_cs);
	return 0;
}

void main()
{
	InitializeCriticalSection(PCRITICAL_SECTION pcs);	//初始化临界区
	DeleteCriticalSection(PCRITICAL_SECTION pcs);	//销毁临界区
}

CRITICAL_SECTION g_cs: is a data structure, put all the resources to be shared on EnterCriticalSection between (& g_cs) and LeaveCriticalSection (& g_cs), incoming g_cs address when calling.

There is a problem: When the toilet after not marked "no", then everyone can not be on the toilet. If someone wait any longer, forcing the toilet, definitely put the toilet door to break it.

Spin locks and critical sections

When a thread tries to enter a critical section, but the key segment is occupied by another thread, the calling thread function will immediately switch to the standby state, which means that threads from user mode to kernel mode, this switching overhead is very large (approximately 1000 CPU cycle).
In order to improve the performance of critical sections, adding spin lock in key segments, while waiting for the cycle will continue to try to use a spin lock entered a critical period, only after failed attempts, the thread will switch to kernel mode and enters a wait state.

BOOL InitializeCriticalSectionAndSpinCount(
	PCRITICAL_SECTION pcs,	//关键段结构地址
	DWORD dwSpinCount);	//旋转循环的次数
DWORD SetCriticalSectionSpinCount(
		PCRITICAL_SECTION pcs,	//关键段结构地址
	DWORD dwSpinCount);	//旋转循环的次数
//主机只有一个处理器时,函数会忽略dwSpinCount参数

Guess you like

Origin blog.csdn.net/qq_42856154/article/details/90756519
Recommended