临界区锁 InitializeCriticalSection()--- EnterCriticalSection()--LeaveCriticalSection()

2023-10-27

1、


InitializeCriticalSection

此函数初始化一个临界区对象。

格式:

void InitializeCriticalSection(  LPCRITICAL_SECTION lpCriticalSection);

参数:lpCriticalSection指向临界区对象的指针。

返回值:无

      单个进程的线程可以使用一个互斥同步临界区对象。虽然对线程将获得临界区所有权的顺序没有保证,该系统将处理所有线程的所有权要求。

这个进程负责分配一个临界区对象使用的内存,它可以通过声明类型的CRITICAL_SECTION的变量使用的内存。在使用一个临界区对象以前,一些进程中的线程必须调用InitializeCriticalSection函数来初始化对象。

一旦一个临界区对象已被初始化,该进程的线程可以在EnterCriticalSection或LeaveCriticalSection函数指定对象,提供对共享资源的相互独占式访问。对于不同进程之间的类似线程同步,使用互斥对象。

一个临界区对象不能移动或复制。这一进程也绝不能修改该对象,但必须把它作为逻辑不透明来处理。只能使用由与Microsoft Win32 ® API提供的临界区功能,用来管理临界区对象。

在低内存的情况下,InitializeCriticalSection可能提出STATUS_NO_MEMORY异常。


========

2、DeleteCriticalSection

删除关键节对象释放由该对象使用的所有系统资源。

  void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);

参数:  lpCriticalSection, 对关键节对象的指针。先前必须已将该对象初始化与InitializeCriticalSection函数中。

=================

3、线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法

注:使用结构CRITICAL_SECTION 需加入头文件#include “afxmt.h”

定义一个全局的锁 CRITICAL_SECTION的实例
和一个静态全局变量

  1. CRITICAL_SECTION cs;//可以理解为锁定一个资源
  2. static int n_AddValue = 0;//定义一个静态的全部变量n_AddValue

创建两个线程函数,代码实现如下:

  1. //第一个线程
  2. UINT FirstThread(LPVOID lParam)
  3. {
  4.     EnterCriticalSection(&cs);//加锁 接下来的代码处理过程中不允许其他线程进行操作,除非遇到LeaveCriticalSection
  5.     for(int i = 0i<10i++){       
  6.         n_AddValue ++;
  7.         cout << "n_AddValue in FirstThread is "<<n_AddValue <<endl;       
  8.    
  9.     }
  10.     LeaveCriticalSection(&cs);//解锁 到EnterCriticalSection之间代码资源已经释放了,其他线程可以进行操作   
  11.     return 0;
  12.  
  13. }
  14.  
  15. //第二个线程
  16. UINT SecondThread(LPVOID lParam)
  17. {
  18.     EnterCriticalSection(&cs);//加锁
  19.     for(int i = 0i<10i++){       
  20.         n_AddValue ++;       
  21.         cout << "n_AddValue in SecondThread is "<<n_AddValue <<endl;   
  22.        
  23.     }
  24.     LeaveCriticalSection(&cs);//解锁
  25.  
  26.     return 0;
  27.  
  28. }

在主函数添加以下代码

  1. int _tmain(int argcTCHARargv[]TCHARenvp[])
  2. {
  3.     int nRetCode = 0;
  4.  
  5.     // 初始化 MFC 并在失败时显示错误
  6.     if (!AfxWinInit(::GetModuleHandle(NULL)NULL, ::GetCommandLine()0))
  7.     {
  8.         // TODO: 更改错误代码以符合您的需要
  9.         _tprintf(_T("错误: MFC 初始化失败/n"));
  10.         nRetCode = 1;
  11.     }
  12.     else
  13.     {
  14.  
  15.         InitializeCriticalSection(&cs);//初始化结构CRITICAL_SECTION
  16.  
  17.  
  18.         CWinThread *pFirstThread,*pSecondThread;//存储函数AfxBeginThread返回的CWinThread指针
  19.        
  20.  
  21.         pFirstThread  = AfxBeginThread(FirstThread,LPVOID(NULL));//启动第一个线程
  22.         pSecondThread = AfxBeginThread(SecondThread,LPVOID(NULL));//启动第二个线程
  23.  
  24.         HANDLE hThreadHandle[2];//
  25.         hThreadHandle[0] = pFirstThread->m_hThread;
  26.         hThreadHandle[1] = pSecondThread->m_hThread;
  27.  
  28.         //等待线程返回
  29.         WaitForMultipleObjects(2,hThreadHandle,TRUE,INFINITE);       
  30.     }
  31.  
  32.     return nRetCode;
  33. }

输出:

n_AddValue in FirstThread is 1
n_AddValue in FirstThread is 2
n_AddValue in FirstThread is 3
n_AddValue in FirstThread is 4
n_AddValue in FirstThread is 5
n_AddValue in FirstThread is 6
n_AddValue in FirstThread is 7
n_AddValue in FirstThread is 8
n_AddValue in FirstThread is 9
n_AddValue in FirstThread is 10
n_AddValue in SecondThread is 11
n_AddValue in SecondThread is 12
n_AddValue in SecondThread is 13
n_AddValue in SecondThread is 14
n_AddValue in SecondThread is 15
n_AddValue in SecondThread is 16
n_AddValue in SecondThread is 17
n_AddValue in SecondThread is 18
n_AddValue in SecondThread is 19
n_AddValue in SecondThread is 20

如果把两个线程函数中的EnterCriticalSection和LeaveCriticalSection位置移到for循环中去,线程的执行顺序将会改变
输出也就跟着改变,如:

  1. //第一个线程
  2. UINT FirstThread(LPVOID lParam)
  3. {
  4.    
  5.     for(int i = 0i<10i++){
  6.         EnterCriticalSection(&cs);//加锁 锁移到for循环内部里
  7.         n_AddValue ++;
  8.         cout << "n_AddValue in FirstThread is "<<n_AddValue <<endl;   
  9.         LeaveCriticalSection(&cs);//解锁 
  10.     }   
  11.     return 0;
  12. }
  13.  
  14. //第二个线程
  15. UINT SecondThread(LPVOID lParam)
  16. {
  17.    
  18.     for(int i = 0i<10i++){   
  19.         EnterCriticalSection(&cs);//加锁
  20.         n_AddValue ++;       
  21.         cout << "n_AddValue in SecondThread is "<<n_AddValue <<endl;
  22.         LeaveCriticalSection(&cs);//解锁       
  23.     }
  24.     return 0;
  25. }

其他代码不变,输出的结果如下:

n_AddValue in FirstThread is 1
n_AddValue in SecondThread is 2
n_AddValue in FirstThread is 3
n_AddValue in SecondThread is 4
n_AddValue in FirstThread is 5
n_AddValue in SecondThread is 6
n_AddValue in FirstThread is 7
n_AddValue in SecondThread is 8
n_AddValue in FirstThread is 9
n_AddValue in SecondThread is 10
n_AddValue in FirstThread is 11
n_AddValue in SecondThread is 12
n_AddValue in FirstThread is 13
n_AddValue in SecondThread is 14
n_AddValue in FirstThread is 15
n_AddValue in SecondThread is 16
n_AddValue in FirstThread is 17
n_AddValue in SecondThread is 18
n_AddValue in FirstThread is 19
n_AddValue in SecondThread is 20

个人认为在函数EnterCriticalSection和LeaveCriticalSection中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中
的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性


http://blog.csdn.net/ccrrt/article/details/8099297



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

临界区锁 InitializeCriticalSection()--- EnterCriticalSection()--LeaveCriticalSection() 的相关文章

随机推荐

  • eclipse修改默认工作空间

    如果勾选了Use this as the default and do not ask again下次要启动时不会再次显示修改工作空间的选择 要改变工作空间的方法 有3中方法可以更改workspace的路径设置 1 启动Eclipse My
  • opencv实现打开摄像头及视频文件

    完整人脸识别系统 源码 教程 环境 开源毕业设计 基于嵌入式ARM Linux的应用OpenCV和QT实现的人脸识别系统 源码 论文 完全毕设教程 Linux上Opencv与Qt实现的人脸识别的考勤点名 门禁系统 PC与嵌入式ARM版本 本
  • 从用户故事说起,谈谈怎么写TAPD的需求说明

    公司经常用 TAPD 来进行需求管理与敏捷迭代 那么针对 TAPD 上的第一步需求记录应该怎么写呢 本人就做了一个小小的总结与归纳 助力产品更加方便准确地完成需求的填写 什么是需求 需求 User Story 用户故事是从用户角度来描述用户
  • sqli-labs靶场15-19关通关笔记中总结

    第十五关 本关属于时间注入 基于源码分析 闭合字符是单引号 本关没有错误提示 那么我们只能靠猜测进行注入 这里我直接从源代码中看到了 sql语句 那这里对 id 进行 id 的处理 本关我们利用延时注入进行 uname admin and
  • 计算机网络练习题-3

    若主机H2向主机H4发送1个数据帧 主机H4向H2立即发送一个确认帧 则除H4外 从物理层上能够收到该确认帧的主机还有 D A 仅H2 B 仅H3 C 仅H1 H2 D 仅H2 H3 解析 关于物理层 数据链路层 网络层设备对于隔离冲突域的
  • Java对象逃逸及逃逸分析

    1 Java对象在堆中分配内存是否绝对 Java中对象一般在堆中分配内存 但是存在特殊情况 如果经过逃逸分析之后发现 对象并没有逃逸出方法的话 就可能被优化成栈上分配内存 优点 栈中分配内存 随着方法的执行结束 栈空间被自动移除 无须进行垃
  • 使用MMDetection3.x训练自定义数据集和类别

    使用MMDetection3 x训练自定义数据集和类别 1 安装 2 训练 2 1 准备数据和配置文件 2 2 训练 2 3 测试 3 评价指标 Evaluation Metrics 3 1 目标检测评估 Detection Evaluat
  • jQuery01-入门-选择器

    目录 一 What 是什么 二 Why 为什么要学习 三 Where 哪些情况下用 四 How 怎么用 五 jQuery选择器 层次选择器 二 过滤选择器 三 表单选择器 一 What 是什么 JavaScript库 封装了很多JS代码 J
  • java第三课——数据类型与变量

    目录 一 字面常量 二 数据类型 2 1数据类型的分类 2 2详解基本数据类型 三 变量 3 1定义变量的语法格式 3 2整型变量 3 3浮点型变量 3 4字符型变量 3 5布尔型变量 3 6类型转换 3 6 1自动类型转换实例 3 6 2
  • 用 visio 2013 让插入的图片倾斜

    选中需要倾斜的图片 依次点击 开始 效果 三维旋转 选择需要旋转的形式即可
  • java反序列化漏洞利用工具_Shiro反序列化漏洞利用汇总

    Apache Shiro是一个强大易用的Java安全框架 提供了认证 授权 加密和会话管理等功能 Shiro框架直观 易用 同时也能提供健壮的安全性 1 Shiro rememberMe反序列化漏洞 Shiro 550 1 1 漏洞原理 1
  • Angular2时间控件,多选下拉框,滑动菜单

    https cuppalabs github io components
  • DLL的编码

    cdecl 是C Declaration的缩写 declaration 声明 表示C语言默认的函数调用方法 所有参数从右到左依次入栈 这些参数由调用者清除 称为手动清栈 被调用函数 不会要求调用者传递多少参数 调用者传递过多或者过少的参数
  • 巴比特

    摘要 腾讯将于明日正式公布旗下大模型和 AI 聊天机器人 然而在发布前一天 微信就已经揭示了相关命名和图标 微信公众号和小程序显示 腾讯的 AI 大模型被命名为 腾讯混元大模型 多模态对话机器人被命名为 腾讯混元助手 图片来源 由无界AI生
  • [Mac OS X] 如何解决 “dtrace cannot control executables signed with restricted entitlements”?

    本文转载并参考至 http stackoverflow com questions 33476432 is there a workaround for dtrace cannot control executables signed wi
  • 用Python实现一个可定制风格的绘图系统

    文章目录 调用绘图风格控件 代码组织 源代码 base py aframe py alist py ds py Python绘图系统 从0开始的3D绘图系统 一套3D坐标 多个函数 散点图 极坐标和子图 自定义控件 绘图风格 风格控件 图表
  • 基于LSP的网络数据包截获(一) SPI

    SPI是Service Provider Interface WinSock2的服务提供者接口 WinSock2允许开发者编写自己的服务提供者接口SPI程序 自己编写的SPI程序安装到系统后 所有的WinSock请求会先发送到这个程序并由他
  • 基于OpenCV的硬币面值识别

    本项目通过Python与Opencv结合数字图像处理技术对 元 角 角三种硬币进行识别 首先通过Canny算子对图像进行边缘检测 然后进一步调用定义的函数去除边缘检测后图像中的孤立点 对处理后的图像进行Hough变换检测圆曲线 进而可以把圆
  • 橙子科技php_ser靶场学习记录

    该靶场为重庆橙子科技制作 主要是为了教学引导用的 所以里面的大部分题都不能算严格意义上的ctf题目 但是 这些题目可以很好地帮助理解并运用PHP反序列化知识 由于本文是我做靶场题目时分析题目的纯记录 当时没有认真写 所以可读性会不太好 Do
  • 临界区锁 InitializeCriticalSection()--- EnterCriticalSection()--LeaveCriticalSection()

    1 InitializeCriticalSection 此函数初始化一个临界区对象 格式 void InitializeCriticalSection LPCRITICAL SECTION lpCriticalSection 参数 lpCr