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

2023-11-07








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中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中
的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性


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

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

  • Windows.Automation 中的旧版 IAccessible

    如何使用C 获取AutomationElement的LegacyIAccessible State和其他LegacyIAccessibles 就像工具中的 Inspect exe 一样 The LegacyIAccessible是新的 并且
  • 向 Windows 服务发送 Windows 消息

    有没有任何工具可以将 WM ENDSESSION 等 Windows 消息发送 模仿 到 Windows 服务 OR 如何使用 C 向进程发送 Windows 消息 我只懂C 编辑 目的 基本上我必须调试 Windows 服务来修复仅在系统
  • WritePrivateProfileString 未在末尾添加属性

    我正在使用以下命令在 ini 文件中写入一些属性WritePrivateProfileString函数并且一切正常 但是当我添加多行文本时 出现了问题 这是代码和输出 WritePrivateProfileString T General
  • 屏幕截图忽略了一些窗口

    我正在 MFC 中工作 我正在尝试捕获桌面的 bmp 我正在使用 GetDC NULL 来执行此操作 但它似乎忽略了特殊的皮肤窗口 它似乎忽略了用 UpdateLayeredWindow 绘制的窗口 此行为似乎仅发生在 Vista x64
  • WaitForSingleObject 是否充当内存屏障?

    昨天一个关于双重检查锁定的问题引发了一系列的想法 让我对一个简单的情况感到不确定 在下面的代码中 是否可以点击printf 不再同步 在这个简单的示例中 这些值可能位于同一缓存行上 因此我认为这种可能性较小 假设一开始可能性 gt 0 如果
  • 低级挂钩/SetWindowsHookEx lParam 自动重复?

    在这里阅读 Windows PC 上如何实现键盘自动重复 https stackoverflow com questions 876852 how is keyboard auto repeat implemented on a windo
  • 如何在 MFC 中创建带圆角的进度控件?

    我需要在 MFC 应用程序中创建一个带圆角的进度条 我尝试过使用 CreateRoundRectRgn 和 SetWindowRgn 的组合 它具有使控件完全消失的效果 我还尝试使用透明的 GIF 覆盖层 该覆盖层将绘制在进度栏的顶部 但我
  • 如何在Windows上用C语言实现定时器

    如何在 C 中创建一个计时器 时间到期后 我应该能够调用回调函数 平台是windows 有人可以指导我吗 问候 米敦 看一眼SetTimer http msdn microsoft com en us library ms644906 28
  • Windows 上的 wchar_t 和 char16_t 是一样的吗?

    我有一个实例std u16string 我可以通过它吗c str 到一个 Win32 API 它期望LPCWSTR 没有任何类型的转换 例如 我可以安全地这样做吗 auto u16s std u16string u Hello SetWin
  • 如何在 Windows 上查找当前系统缓存大小?

    到处搜索 但未能找到 API 调用来检索 Windows 上 文件 系统缓存的当前大小 全局内存状态Ex https stackoverflow com a 2017659 450917 检索总计 免费 已用和交换统计数据 获取系统文件缓存
  • 尝试使用 LoadImage 加载应用程序的图标,但该函数返回 0

    我正在尝试使用加载应用程序的图标LoadImageWinAPI函数 但由于某种原因它总是返回0 我已阅读文档 https msdn microsoft com en us library windows desktop ms648045 v
  • 如何正确使用和实例化现有预览处理程序

    我正在尝试使用现有的预览处理程序来显示文件的预览 我编写了一个简单的测试程序 以 1 查找给定文件的预览处理程序的 CLSID 2 实例化预览处理程序 3 通过流或文件初始化它 4 在基本窗口上渲染预览 这有效 或多或少 It works
  • Win32 自定义绘制树视图控件

    我正在尝试使用 NM CUSTOMDRAW 消息自定义树视图控件 我只是想用灰色绘制所有其他可见的项目 这是绘制的代码 INT CResourceOutliner On WM NOTIFY HWND hDlg WPARAM wParam L
  • 获取保证具有完整(4 位)年份的 LOCALE_SSHORTDATE 的正确方法是什么?

    我想创建一个日期时间选择器控件 它显示日期和时间 作为DTS SHORTDATECENTURYFORMAT and DTS TIMEFORMAT风格 由于日期时间选择器中没有内置这种样式 因此我必须自己做GetLocaleInfoEx 我注
  • 如何删除非空约束?

    假设创建了一个表 如下所示 create table testTable colA int not null 您将如何删除非空约束 我正在寻找类似的东西 ALTER TABLE testTable ALTER COLUMN colA DRO
  • 使用 CreateRestrictedToken(LUA_TOKEN) 从提升的进程创建低/中进程

    我正在尝试从提升的进程创建中或低完整性进程 我知道还有其他类似的问题 但它们主要关注使用资源管理器或任务计划程序等解决方法 我想坚持使用CreateRestrictedToken CreateProcessAsUser 我认为一定可以以某种
  • 如何使用 Python 与窗口的 GUI 交互?

    假设您想打开myapp exe 打开第三个菜单 然后选择第二个菜单项 即像用户使用键盘或鼠标一样 然后在对话框窗口中选择第二个按钮 pyahk https pyahk readthedocs io en latest and pyautog
  • 从模态 MFC 表单获取输入信息

    我已经创建了表格CPreparationDlg具有Edit Control 然后我创建了创建模态表单的应用程序 在按 确定 后 我需要将编辑控件中输入的文本读入主程序的变量中 最好的方法是什么 class CPreparationApp p
  • 调整大小时在窗口中绘图留下未绘制的边框

    我遇到的问题看似微不足道 但我找不到解决的方法 这里是 我有一个窗口 里面有一些图形 为了简单起见 我们假设它是一个实心绿色矩形 填充了窗口的整个客户区域 我希望每次窗口改变大小时都重新绘制这个矩形并填充整个窗口 我最初做的就是这样的 我已
  • 如何查明 .exe 是否正在 C++ 中运行?

    给定进程名称 例如 程序 exe C 标准库没有这样的支持 您需要一个操作系统 API 来执行此操作 如果这是 Windows 那么您将使用 CreateToolhelp32Snapshot 然后使用 Process32First 和 Pr

随机推荐

  • less动态样式语言(预处理语言)

    一 使用方法 Less是一门CSS 预处理语言 它扩展了 CSS 语言 增加了变量 Mixin 函数等特性 使 CSS 更易维护和扩展 Less 可以运行在 Node 或浏览器端 1 客户端使用 1 下载less 2 编写项目less文件
  • 红米10A 一键root教程 解锁BL 跳过168小时限制 刷面具root救黑砖刷机 解决无法解锁BL 新版本刷机

    新版本 红米10A 解锁BL 无法秒解锁BL root bootloader 要刷机 线刷救砖 获取Root权限都需要解除bootloader锁 我们称解除刷机限制的这个操作就叫解锁BL 只有解锁BL后 才可以进行刷机 刷Root权限等等一
  • Linux多进程:orphan process——孤儿进程

    孤儿进程orphan process 当父进程比子进程先结束 这样的子进程就成为了孤儿进程 每当出现一个孤儿进程 内核会把孤儿进程的父进程设置为init 托管 init进程会循环wait 孤儿进程结束 然后做剩下的善后 回收资源 因此 孤儿
  • 验证链表是否有环

    思路 声明一个快指针 一个慢指针 快指针一次走两步 慢指针一次走一步 如果快慢两个指针相遇 说明链表有环 至于为什么快慢两个指针相遇就说明链表中有环 这个牵扯到数学证明 这里就不论证了 我们直接用结论 代码实现 初始化的时候 快指针指向 h
  • SSM框架学习(三),SSM整合

    主要整合的主要整合Spring和Mybatis 将Mybatis交由Spring管理 第一步配置datasource
  • 因找不到D3DCompiler_47.dll文件导致游戏软件无法启动问题

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库 这时你可以下载这个D3DComp
  • jdbc中加载oracle驱动程序,在一个Java应用程序中使用多个Oracle JDBC驱动程序?

    我想通过JDBC连接到两个不同的Oracle数据库 一个8 0 5 0 0和一个12c 我确实有两个JDBC驱动程序 它们可以通过简单的 hello world 应用程序分别成功地连接到相应的DB 下面 我将它们都放在一个Java应用程序中
  • 【R语言】实验五 综合应用

    系列文章目录 实验一 R 语言数据结构 数据导入与数据处理 实验二 基本数据处理 实验三 数据可视化 实验四 数据分析 实验五 综合应用 实验数据 实验数据下载 1 systation 数据集 systation csv 中包含的是沈阳地铁
  • springmvc_上传图片以及显示图片到页面

    首先我使用的开发工具是IntelliJ idea 今天想做一个上传头像以及显示头像的简单功能 也在网上查询了很多资料 真的看得头大 最后还是自己鼓捣出来了 明明很简单的一个功能 先看看效果吧 需要注意的地方 1 记住要在wepapp文件目录
  • 必看,Mac苹果电脑重装系统教程

    们在使用mac电脑的过程中 因为Mac电脑长时间使用或多或少都可能会出现一些问题 这个时候我们可以选择重新安装系统来解决这些问题 Mac电脑重装系统方法其实很简单 分为两种 一种可以在线重装系统 一种可以将Mac系统制作到U盘里进行系统重装
  • ubuntu pptp

    Hi 1 安装pptp linux sudo apt get install pptp linux binutils 2 建立pptp连接 sudo pptpsetup create testvpn server 45 77 243 243
  • 在Ubuntu18.04上安装Docker CE的方法

    卸载旧版本 如果之前安装旧版本 需要先卸载 1 sudoapt get remove docker docker engine docker io containerd runc 设置仓库 更新apt包索引 1 sudoapt get up
  • Java实验3 员工管理系统

    Java实验3 员工管理系统 文章目录 Java实验3 员工管理系统 toc 1 实验要求 2 具体创建过程 3 结果展示 4 代码展示 1 实验要求 进行一个企业员工基本信息的数据库设计 使用员工信息表 部门信息表两个数据表来存放数据 选
  • SSM集成Redis的小案例

    一 详情介绍 这里是使用Window版本的Redis 将下载好的Windows版本的Redis压缩包解压到一个目录下 客户端使用的是Redis Desktop Manager 使用Redis需要启动相应的服务 操作如下图所示 备注 双击打开
  • LDAP应用技术简述

    LDAP应用技术简述 一 一 简介 a X500 目录服务 OSL X 500目录是基于OSI网络协议的目录服务协议 也是LDAP的前身 但是X 500的缺点是不支持TCP IP 而是支持OSI协议 显然 在 Windows等个人电脑上不可
  • Jenkins

    Jenkins 文章目录 Jenkins 1 Jenkins概述 Jenkins特性 2 系统集成工具 Jenkins和Hudson 3 部署方案 手动部署流程 自动化署流程 4 Jenkins svn自动部署 环境准备 yum部署Jenk
  • Linux安装Oracle JDK

    从公司云平台申请的虚拟机默认安装了open jdk 想改成oracle 官方的jdk 1 检查系统jdk版本 root localhost software java version openjdk version 1 8 0 102 Op
  • vue js 获取yaml文件内容并且将文件内容转换为JSON

    写在公共js内 export function eadFile file const reader new FileReader const promise new Promise resolve reject gt reader onlo
  • 通过libusb读取鼠标数据

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

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