Source: WeChat Official Account "Programming Learning Base"
Thread synchronization
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 WaitForSingleObject
thread 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