接上一篇,我们来看另一种实现临界区顺序访问的方法
这次我们使用,InitializeCriticalSection, EnterCriticalSection,LeaveCriticalSection,DeleteCriticalSection
要使用这些需要包含windows.h并定义一个CRITICAL_SECTION变量
那么这种方式与上一篇中用互斥量实现的方式有什么差别呢?
下面是实现的代码:

View Code

#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实现的方式,线程访问临界区的次数基本上是和线程本身执行的快慢成正比的
用互斥量实现的方式,线程访问临界区的次数基本上是相等的。
所以要根据实际使用的场景选择合适的方式
进一步可有用下面的代码来验证上面的结论

View Code

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 临界区相关推荐

  1. Windows临界区

    一.windows临界区 Windows临界区:(使用前必须初始化) //创建:CRITICAL_SECTION my_winsec;//创建windows中的临界区,类似与互斥量,使用前必须初始化/ ...

  2. Windows 临界区(CRITICAL_SECTION)的使用

    由于需要在多线程中并发操作临界数据,为了保证临界数据操作的完整性,Linux下使用锁(Linux下锁可以看我的这篇博客Linux 互斥锁 递归锁 自旋锁 读写锁),而在Windows下,使用的是临界区 ...

  3. Windows临界区简单实现

    最近看的书中介绍了线程临界区同步方式,思考之前写过的内存释放相关结构便动手实现一个简易的临界区(支持多个线程同时使用). 关于结构设计的几点介绍:   1.设计采用了先进先出概念,当第一个线程进入临界 ...

  4. C++11 多线程库使用说明

    多线程基础 1.1 进程与线程 根本区别: 进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位 开销方面: 每个进程都有自己独立的代码和数据空间,程序之间的切换开销较大. 线程可以看作是 ...

  5. 【C++】【设计模式之】生产者-消费者模型(理论讲解及实现)

    一.什么是生产者-消费者模型 1.简单理解生产者-消费者模型 假设有两个进程(或线程)A.B和一个固定大小的缓冲区,A进程生产数据放入缓冲区,B进程从缓冲区中取出数据进行计算,这就是一个简单的生产者- ...

  6. 编程知识点、技能点汇集收录

    0.嵌入式 微信公众号:嵌入式大杂烩 https://mp.weixin.qq.com/s/fOIZHHPhXCVUfndUZXBQ9Q 1.纯软件 主要内容取自微信公众号:高性能服务器开发 http ...

  7. c++语言从入门到精通教程,C++从入门到精通 C++98视频课程

    『课程目录』: 目录:/C++从入门到精通 C++98 11 14 17视频课程 ┣━━1-1 c++ 语言课程详细介绍.mp4 ┣━━2-1 语言特性.工程构成.可移植性.mp4 ┣━━2-9 迭代 ...

  8. windows多线程同步--临界区

    推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念,一般操作系统书上面都有. 适用范围:它只能同步一个进程中的线程,不能跨进程同步.一般用它来做单个进程内的代码快同步,效率比较 ...

  9. Windows编程-- 用户方式中线程的同步---关键代码段(临界区)

    可以从例子学习,更好的掌握 #include <windows.h> #include <iostream.h> //两个线程的声明 DWORD WINAPI Fun1Proc ...

最新文章

  1. Extjs遇到的一些问题
  2. 请写出至少五个块级元素_2020高考元素化合物命题特点及复习思路
  3. Ubuntu上安装Maven3
  4. DevExpress下拉多选框 CheckComboboxEdit、CheckedListBoxControl
  5. canvas节点无法导出图片_开源小程序,练手必备,仿“美图秀秀”处理图片。
  6. vscode的IntelliCode扩展报错
  7. 关于minigui的皮肤控件无法显示问题
  8. VMware 虚拟机安装 android-x86_64 iso镜像
  9. VS编译的程序设置----需要以管理员身份打开
  10. php mysql_query 返回值
  11. xshell中重启指令_xshell常用命令大全
  12. 校园网 显示ldap服务器连接不上,客户端无法连接到LDAP服务器
  13. 正态分布方法判别,独立样本T检验及Mann-Whitney U 检验操作
  14. 左神算法:找到二叉树中的最大搜索二叉子树(树形dp套路,Java版)
  15. 点击百度网盘安装包无反应
  16. 异形与铁血战士关系 时间线
  17. could not initialize proxy -the owning Session was closed解决方法
  18. 一个程序员的奋斗txt
  19. 数据库课程设计-----------学生选课管理系统的设计
  20. iOS开发人员必看的精品资料(100个)(转)

热门文章

  1. MAC 修改文件夹以及子文件夹和子文件权限 以及 修改文件夹owner
  2. python环境变量配置步骤_关于人工智能Python系统环境变量设置步骤
  3. python文字游戏 生成数字菜单_pygame游戏之旅 游戏中添加显示文字
  4. 麒麟710f能否升级到鸿蒙系统,定了!麒麟710以上支持升级鸿蒙系统,荣耀也可以升级...
  5. java伪代码生成器_JAVA单例模式的实现伪代码
  6. Java中继承、this关键字、super关键字
  7. 解构产品经理的技术思维
  8. java定义数组_java中数组的三种定义方式_java中数组的定义及使用方法(推荐)...
  9. python没有代码提示怎么设置_Python Kite 使用教程 轻量级代码提示
  10. 计量科学大数据分级分类