C++拾遗--多线程:临界区解决子线程的互斥
为了解决子线程的互斥问题,windows系统提出了关键段或临界区(CRITICAL_SECTION)的概念。它一共有四个共两对操作:初始化、销毁,进入、离开。它们定义在头文件synchapi.h中。
1.初始化变量
VOID WINAPI InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
2.销毁变量
VOID WINAPI DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
3.进入临界区域
VOID WINAPI EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
函数说明:系统保证各个子线程互斥的进入临界区域
4.离开临界区域
VOID WINAPI LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
四个函数的使用都相当简单,传入CRITICAL_SECTION类型的变量地址即可。
下面我们使用关键段来解决子线程的互斥问题,程序代码类似于原子操作解决线程冲突。每一个子线程都对同一个全局变量累加10。这次我们开启50个子线程,查看最后的累加结果。
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <Windows.h>
#define Thread_NUM 50
CRITICAL_SECTION cs;
int g_count = 0;
void count(void *p)
{
Sleep(100); //do some work
//每个线程把g_count加1共10次
for (int i = 0; i < 10; i++)
{
//进入临界区域
EnterCriticalSection(&cs);
g_count++;
//离开临界区域
LeaveCriticalSection(&cs);
}
Sleep(100); //do some work
}
int main(void)
{
printf("******临界区解决子线程冲突演示***by David***\n");
//初始化关键段变量cs
InitializeCriticalSection(&cs);
//共创建Thread_NUM个线程
HANDLE handles[Thread_NUM];
//共验证10次
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < Thread_NUM; j++)
{
handles[j] = _beginthread(count, 0, NULL);
}
WaitForMultipleObjects(Thread_NUM, handles, 1, INFINITE);
printf("%d time g_count = %d\n", i, g_count);
//重置
g_count = 0;
}
//销毁关键段变量cs
DeleteCriticalSection(&cs);
getchar();
return 0;
}运行
从运行结果看,使用关键段确实可以解决子线程的冲突问题。在g_count++;的前后我们加上关键段的进入和离开,使这句代码成为了“临界”区域。至此,g_count++;的操作就十分类似于原子操作。下面我们来详细分析下关键段的使用原理。
关键段的定义
在minwinbase.h中
typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
而在winnt.h中
typedef struct _RTL_CRITICAL_SECTION {
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
//
// The following three fields control entering and exiting the critical
// section for the resource
//
LONG LockCount;
LONG RecursionCount;
HANDLE OwningThread; // from the thread‘s ClientId->UniqueThread
HANDLE LockSemaphore;
ULONG_PTR SpinCount; // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
关键段就是一结构体。具体原因后续分析……
本专栏目录
原文:http://blog.csdn.net/zhangxiangdavaid/article/details/43983921