CRITICAL_SECTION
在Windows操作系统中通常用于同步多个线程,确保一次只有一个线程可以访问特定的代码段或资源。这对于防止数据竞争和不一致至关重要。以下是使用 CRITICAL_SECTION
的基本步骤:
-
声明和初始化:
首先,你需要声明一个CRITICAL_SECTION
类型的变量。然后,使用InitializeCriticalSection
函数来初始化这个变量。CRITICAL_SECTION cs; InitializeCriticalSection(&cs);
-
进入临界区:
在你想要保护的代码段之前,使用EnterCriticalSection
函数进入临界区。这将阻止其他线程进入临界区,直到当前线程离开临界区。EnterCriticalSection(&cs);
-
访问共享资源:
在EnterCriticalSection
和LeaveCriticalSection
之间,你可以安全地访问共享资源,不会有其他线程同时访问。g_sharedResource = newValue;
-
离开临界区:
一旦你完成了对共享资源的访问,使用LeaveCriticalSection
函数来离开临界区。这将允许其他线程进入临界区。LeaveCriticalSection(&cs);
-
销毁临界区:
当你的程序不再需要临界区时,使用DeleteCriticalSection
函数来销毁它。DeleteCriticalSection(&cs);
注意:
- 确保每个
EnterCriticalSection
调用都有一个相应的LeaveCriticalSection
调用,否则会导致死锁。 CRITICAL_SECTION
不是递归的,意味着同一个线程不能多次进入同一个临界区而不先离开它。- 临界区是进程内的同步机制,不适用于跨进程的同步。
- 当你使用
CRITICAL_SECTION
时,通常应该避免长时间持有临界区,因为这可能会阻塞其他线程,并降低程序的整体性能。
实例:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
// 定义全局临界区对象
CRITICAL_SECTION g_cs;
// 定义全局共享资源
int g_sharedResource = 0;
// 线程函数
DWORD WINAPI ThreadProc(LPVOID pParam) {
for (int i = 0; i < 1000; i++) {
// 进入临界区
EnterCriticalSection(&g_cs);
// 对共享资源进行增加操作
g_sharedResource++;
// 离开临界区
LeaveCriticalSection(&g_cs);
// 为了展示效果,可以让线程休眠一下
Sleep(1);
}
return 0;
}
int main() {
// 初始化临界区
InitializeCriticalSection(&g_cs);
// 创建线程
HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
// 等待线程结束
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
// 打印共享资源的最终值
printf("Final value of shared resource: %d\n", g_sharedResource);
// 销毁临界区
DeleteCriticalSection(&g_cs);
// 关闭线程句柄
CloseHandle(hThread1);
CloseHandle(hThread2);
return 0;
}