线程锁EnterCriticalSection和LeaveCriticalSection的用法

线程锁EnterCriticalSection和LeaveCriticalSection的用法线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法注:使用结构CRITICAL_SECTION需加入头文件#include“afxmt.h”定义一个全局的锁CRITICAL_SECTION的实例  和一个静态全局变量CRITICAL_SECTIONcs;//可以理解为锁定一个资源staticintn_AddVal

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法
注:使用结构CRITICAL_SECTION 需加入头文件#include “afxmt.h”
定义一个全局的锁 CRITICAL_SECTION的实例

  和一个静态全局变量
CRITICAL_SECTION cs;//可以理解为锁定一个资源
static int n_AddValue = 0;//定义一个静态的全部变量n_AddValue
创建两个线程函数,代码实现如下:
//第一个线程
UINT FirstThread(LPVOID lParam)
{
EnterCriticalSection(&cs);//加锁 接下来的代码处理过程中不允许其他线程进行操作,除非遇到LeaveCriticalSection
for(int i = 0; i<10; i++){
n_AddValue ++;
cout << “n_AddValue in FirstThread is “<<n_AddValue <<endl;
}
LeaveCriticalSection(&cs);//解锁 到EnterCriticalSection之间代码资源已经释放了,其他线程可以进行操作
return 0;
}
//第二个线程
UINT SecondThread(LPVOID lParam)
{
EnterCriticalSection(&cs);//加锁
for(int i = 0; i<10; i++){
n_AddValue ++;
cout << “n_AddValue in SecondThread is “<<n_AddValue <<endl;
}
LeaveCriticalSection(&cs);//解锁
return 0;
}
在主函数添加以下代码
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T(“错误: MFC 初始化失败/n”));
nRetCode = 1;
}
else
{
InitializeCriticalSection(&cs);//初始化结构CRITICAL_SECTION
CWinThread *pFirstThread,*pSecondThread;//存储函数AfxBeginThread返回的CWinThread指针
pFirstThread = AfxBeginThread(FirstThread,LPVOID(NULL));//启动第一个线程
pSecondThread = AfxBeginThread(SecondThread,LPVOID(NULL));//启动第二个线程
HANDLE hThreadHandle[2];//
hThreadHandle[0] = pFirstThread->m_hThread;
hThreadHandle[1] = pSecondThread->m_hThread;
//等待线程返回
WaitForMultipleObjects(2,hThreadHandle,TRUE,INFINITE);
}
DeleteCriticalSection(&cs);//删除临界区
return nRetCode;
}
输出:
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循环中去,线程的执行顺序将会改变

  输出也就跟着改变,如:
//第一个线程
UINT FirstThread(LPVOID lParam)
{
for(int i = 0; i<10; i++){
EnterCriticalSection(&cs);//加锁 锁移到for循环内部里
n_AddValue ++;
cout << “n_AddValue in FirstThread is “<<n_AddValue <<endl;
LeaveCriticalSection(&cs);//解锁
}
return 0;
}
//第二个线程
UINT SecondThread(LPVOID lParam)
{
for(int i = 0; i<10; i++){
EnterCriticalSection(&cs);//加锁
n_AddValue ++;
cout << “n_AddValue in SecondThread is “<<n_AddValue <<endl;
LeaveCriticalSection(&cs);//解锁
}
return 0;
}
其他代码不变,输出的结果如下:
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中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中

  的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性
[2]
 
使用EnterCriticalSection与LeaveCriticlSection时应注意
若在同一个线程中第一次LeaveCriticlSection与第二次EnterCriticalSection执行间隔较短(如一个循环内的最后一行与第一行),可能导致其他线程无法进入临界区。此时可在LeaveCriticlSection后适当延时。
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
for(;;)
{
EnterCriticalSection(&cs);
cout << “In ThreadProc2” << endl;
LeaveCriticalSection(&cs);
Sleep(100);//若去掉此句 可能导致其他线程无法进入临界区
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/192883.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • WebSocket介绍和Socket的区别

    WebSocket介绍和Socket的区别  WebSocket介绍与原理WebSocketprotocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。——百度百科目的:即时通讯,替代轮询网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是采用轮询、Comet技术解决。HTTP协议是非持久化的,单向的网…

    2022年7月11日
    12
  • 【C语言】getchar 函数的正确使用

    【C语言】getchar 函数的正确使用目录一、getchar函数二、缓冲区1、什么是缓冲区2、为什么要存在缓冲区3、缓冲区的类型4、缓冲区的刷新三、getchar函数的正确使用1、getchar的换行问题2、getchar与scanf的混合使用一、getchar函数从上面的介绍来看,我们要正确使用getchar函数,首先得了解什么是缓冲区。二、缓冲区1、什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

    2022年10月19日
    0
  • winform窗体跳转代码_js在当前页面打开新页面

    winform窗体跳转代码_js在当前页面打开新页面在前台用JS写的脚本方法,除了可以直接用在前台控件的属性中,还可以在后台运用。即在后台页面加载时,调用JS方法。语法格式有两种,如下: 1.第一种写法:控件ID名.Attributes.Add(“事件名称”,“JS方法”);如:一个按钮控件Button1.Attributes.Add(“onclick”,“returnconfirm(‘确认?’)”);

    2022年9月26日
    0
  • 在Eclipse中使用JUnit5进行单元测试

    在Eclipse中使用JUnit5进行单元测试关于Junit的介绍:官方介绍:JUnit5是下一代的JUnit。其目标是为JVM上的开发端测试创建一个最新的基础。这包括关注Java8和以上,以及支持多种不同的测试风格。JUnit5是JUnitLambda及其在Indiegogo上众筹活动的结果。引用度娘的介绍如下:JUnit是一个Java语言的单元测试框架。它由KentBeck和ErichGamma建立,逐渐成…

    2025年6月1日
    0
  • Typescript 教程

    Typescript 教程https://zhongsp.gitbooks.io/typescript-handbook/content/https://ts.xcatliu.com/es6入门http://es6.ruanyifeng.com/#docs/string#%E6%A8%A1%E6%9D%BF%E5%AD%97%E7%AC%A6%E4%B8%B2

    2022年10月25日
    0
  • Brup插件开发手记

    Brup插件开发手记前言在一些攻防演练中,像Shiro、Fastjson等常见高危漏洞一直被高频利用。但在一些情况下,这些漏洞通过几轮的洗刷下来出现的频率会逐渐变少。在打点的时候,一些平时并不会去

    2021年12月13日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号