C++拾遗--多线程:临界区解决子线程的互斥
来源:互联网 发布:手机视频软件免费 编辑:程序博客网 时间:2024/04/30 04:52
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 50CRITICAL_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");//初始化关键段变量csInitializeCriticalSection(&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;}//销毁关键段变量csDeleteCriticalSection(&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++拾遗 目录
- CCPP Blog 目录
- C++拾遗--多线程:临界区解决子线程的互斥
- 利用线程的同步和互斥解决两个消费者两个生产者一个临界区问题
- C++ 临界区 多线程同步互斥
- C++ 临界区 多线程同步互斥
- 临界区实现线程同步互斥
- 线程同步的三种方法(互斥,事件,临界区) 之一 使用临界区对象
- 关于Win32 API(VC作为程序设计语言)的创建线程,解决互斥访问临界资源问题
- C++拾遗--多线程:主线程与子线程的同步
- 临界区的互斥控制
- 临界区的互斥控制
- 临界区的硬件互斥方案
- 互斥和临界区的区别
- 多线程临界区(windows)/互斥(linux)
- 多线程同步方法:临界区、事件、信号量、互斥对象
- 线程同步机制有临界区、互斥、信号量优缺点
- 进程、线程同步互斥学习 —— 临界区
- 线程同步-临界区、互斥对象、事件对象区别
- Delphi线程同步(临界区、互斥、信号量)
- Binary Tree Preorder Traversal
- [vb6.0] 快捷键触发事件
- pthread_getspecific和pthread_setspecific使用
- Picasso——针对Android的一个强大的图像下载和缓存库
- 新南威尔士大学预科部(UFS)入学成绩要求
- C++拾遗--多线程:临界区解决子线程的互斥
- IOS开发初识
- 字符编码:ASCII,Unicode和UTF-8
- Apache HBase 1.0.0 发布
- 如何对字符串本身进行操作来实现逆向输出
- js中with、this的用法
- iOS笔试题(选择题)
- android4.4.4 获取系统相册图片出错的问题(二)
- (四)Tomcat源码解析 - 一次request与response的过程