windows 临界区
接上一篇,我们来看另一种实现临界区顺序访问的方法
这次我们使用,InitializeCriticalSection, EnterCriticalSection,LeaveCriticalSection,DeleteCriticalSection
要使用这些需要包含windows.h并定义一个CRITICAL_SECTION变量
那么这种方式与上一篇中用互斥量实现的方式有什么差别呢?
下面是实现的代码:
#pragma once #include <windows.h> #include <assert.h>class CVCriSection { public:CVCriSection(void);~CVCriSection(void); public:int CsEnter(){EnterCriticalSection(&m_cs); return 0;}int CsLeave(){LeaveCriticalSection(&m_cs); return 0;}protected:CRITICAL_SECTION m_cs; };class CVCriSectionAuto { public: CVCriSectionAuto(CVCriSection* cs){m_cs=cs; m_cs->CsEnter(); }~CVCriSectionAuto(void){m_cs->CsLeave();m_cs=NULL;} private:CVCriSection* m_cs; };CVCriSection::CVCriSection(void) {InitializeCriticalSection(&m_cs); }CVCriSection::~CVCriSection(void) {DeleteCriticalSection(&m_cs); }
有如下的测试代码
CVCriSection cs; int sum=0; int last=0; pthread_mutex_t g_mutex = CreateMutex(NULL, FALSE, NULL); DWORD WINAPI worker(LPVOID lpParameter) {int no= (int)lpParameter;last = no;while (1){CVCriSectionAuto csauto(&cs); //方式1//CCriticalSection cs(g_mutex); //方式2,这种方式下会严格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3个线程具有均等的运行机会//cs.CsEnter();sum=0;for (int i=0; i<=100000; i++)sum += i;if (no != (last+1)%3)printf("not equal\n");last = no;//cs.CsLeave(); } } int main() {for (int i=0; i<3; i++)CreateThread(NULL, 0, worker, (LPVOID)i, 0, NULL);Sleep(20000);return 0; }
当使用方式1(使用CRITICAL_SECTION实现)来实现互斥访问时,上面的代码将会有很多not equal输出。这就是说,三个线程执行的次数是随机的
当使用方式2(使用互斥量实现)来实现互斥访问时,上面的代码将不会有not equal输出。也就是说,三个线程得到了均等的运行机会。它们访问临界区的次数是相当的。
下面的测试代码可以更直观的看出它们的差别:
CVCriSection cs; int sum=0; int last=0; int cnt[3] = {0, 0, 0}; pthread_mutex_t g_mutex = CreateMutex(NULL, FALSE, NULL); DWORD WINAPI worker(LPVOID lpParameter) {int no= (int)lpParameter;last = no;while (1){//CVCriSectionAuto csauto(&cs); //方式1CCriticalSection cs(g_mutex); //方式2,这种方式下会严格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3个线程具有均等的运行机会//cs.CsEnter();sum=0;for (int i=0; i<=100000; i++)sum += i;cnt[no]++;//cs.CsLeave(); } } int main() {for (int i=0; i<3; i++)CreateThread(NULL, 0, worker, (LPVOID)i, 0, NULL);Sleep(5000);for (int j=0; j<3; j++)printf("%d\n", cnt[j]);return 0; }
最后分别输出三个线程分别进入临界区的次数。
总结:
用CRITICAL_SECTION实现的方式,线程访问临界区的次数基本上是和线程本身执行的快慢成正比的
用互斥量实现的方式,线程访问临界区的次数基本上是相等的。
所以要根据实际使用的场景选择合适的方式
进一步可有用下面的代码来验证上面的结论
CVCriSection cs; int sum=0; int last=0; int cnt[3] = {0, 0, 0}; pthread_mutex_t g_mutex = CreateMutex(NULL, FALSE, NULL); DWORD WINAPI worker(LPVOID lpParameter) {int no= (int)lpParameter;last = no;while (1){CVCriSectionAuto csauto(&cs); //方式1//CCriticalSection cs(g_mutex); //方式2,这种方式下会严格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3个线程具有均等的运行机会//cs.CsEnter();sum=0;int add = no*1000;for (int i=0; i<=10000+add; i++)sum += i;cnt[no]++;//cs.CsLeave(); } } int main() {for (int i=0; i<3; i++)CreateThread(NULL, 0, worker, (LPVOID)i, 0, NULL);Sleep(5000);for (int j=0; j<3; j++)printf("%d %d\n", j, cnt[j]);return 0; }
windows 临界区相关推荐
- Windows临界区
一.windows临界区 Windows临界区:(使用前必须初始化) //创建:CRITICAL_SECTION my_winsec;//创建windows中的临界区,类似与互斥量,使用前必须初始化/ ...
- Windows 临界区(CRITICAL_SECTION)的使用
由于需要在多线程中并发操作临界数据,为了保证临界数据操作的完整性,Linux下使用锁(Linux下锁可以看我的这篇博客Linux 互斥锁 递归锁 自旋锁 读写锁),而在Windows下,使用的是临界区 ...
- Windows临界区简单实现
最近看的书中介绍了线程临界区同步方式,思考之前写过的内存释放相关结构便动手实现一个简易的临界区(支持多个线程同时使用). 关于结构设计的几点介绍: 1.设计采用了先进先出概念,当第一个线程进入临界 ...
- C++11 多线程库使用说明
多线程基础 1.1 进程与线程 根本区别: 进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位 开销方面: 每个进程都有自己独立的代码和数据空间,程序之间的切换开销较大. 线程可以看作是 ...
- 【C++】【设计模式之】生产者-消费者模型(理论讲解及实现)
一.什么是生产者-消费者模型 1.简单理解生产者-消费者模型 假设有两个进程(或线程)A.B和一个固定大小的缓冲区,A进程生产数据放入缓冲区,B进程从缓冲区中取出数据进行计算,这就是一个简单的生产者- ...
- 编程知识点、技能点汇集收录
0.嵌入式 微信公众号:嵌入式大杂烩 https://mp.weixin.qq.com/s/fOIZHHPhXCVUfndUZXBQ9Q 1.纯软件 主要内容取自微信公众号:高性能服务器开发 http ...
- c++语言从入门到精通教程,C++从入门到精通 C++98视频课程
『课程目录』: 目录:/C++从入门到精通 C++98 11 14 17视频课程 ┣━━1-1 c++ 语言课程详细介绍.mp4 ┣━━2-1 语言特性.工程构成.可移植性.mp4 ┣━━2-9 迭代 ...
- windows多线程同步--临界区
推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念,一般操作系统书上面都有. 适用范围:它只能同步一个进程中的线程,不能跨进程同步.一般用它来做单个进程内的代码快同步,效率比较 ...
- Windows编程-- 用户方式中线程的同步---关键代码段(临界区)
可以从例子学习,更好的掌握 #include <windows.h> #include <iostream.h> //两个线程的声明 DWORD WINAPI Fun1Proc ...
最新文章
- Extjs遇到的一些问题
- 请写出至少五个块级元素_2020高考元素化合物命题特点及复习思路
- Ubuntu上安装Maven3
- DevExpress下拉多选框 CheckComboboxEdit、CheckedListBoxControl
- canvas节点无法导出图片_开源小程序,练手必备,仿“美图秀秀”处理图片。
- vscode的IntelliCode扩展报错
- 关于minigui的皮肤控件无法显示问题
- VMware 虚拟机安装 android-x86_64 iso镜像
- VS编译的程序设置----需要以管理员身份打开
- php mysql_query 返回值
- xshell中重启指令_xshell常用命令大全
- 校园网 显示ldap服务器连接不上,客户端无法连接到LDAP服务器
- 正态分布方法判别,独立样本T检验及Mann-Whitney U 检验操作
- 左神算法:找到二叉树中的最大搜索二叉子树(树形dp套路,Java版)
- 点击百度网盘安装包无反应
- 异形与铁血战士关系 时间线
- could not initialize proxy -the owning Session was closed解决方法
- 一个程序员的奋斗txt
- 数据库课程设计-----------学生选课管理系统的设计
- iOS开发人员必看的精品资料(100个)(转)
热门文章
- MAC 修改文件夹以及子文件夹和子文件权限 以及 修改文件夹owner
- python环境变量配置步骤_关于人工智能Python系统环境变量设置步骤
- python文字游戏 生成数字菜单_pygame游戏之旅 游戏中添加显示文字
- 麒麟710f能否升级到鸿蒙系统,定了!麒麟710以上支持升级鸿蒙系统,荣耀也可以升级...
- java伪代码生成器_JAVA单例模式的实现伪代码
- Java中继承、this关键字、super关键字
- 解构产品经理的技术思维
- java定义数组_java中数组的三种定义方式_java中数组的定义及使用方法(推荐)...
- python没有代码提示怎么设置_Python Kite 使用教程 轻量级代码提示
- 计量科学大数据分级分类