首页 > 编程语言 > 详细

C++拾遗--多线程:临界区解决子线程的互斥

时间:2015-02-28 23:06:57      阅读:665      评论:0      收藏:0      [点我收藏+]

                  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;


关键段就是一结构体。具体原因后续分析……





本专栏目录

所有内容的目录

C++拾遗--多线程:临界区解决子线程的互斥

原文:http://blog.csdn.net/zhangxiangdavaid/article/details/43983921

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!