MFC线程(二):线程同步临界区CRITICAL SECTION

2024-05-11 11:08

本文主要是介绍MFC线程(二):线程同步临界区CRITICAL SECTION,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当多个线程同时使用相同的资源时,由于是并发执行,不能保证先后顺序.所以假如时一个公共变量被几个线程同时使用会造成该变量值的混乱.

下面来举个简单例子.

假如有一个字符数组变量

char g_charArray[4];

CString szResult;

AfxBeginThread(FunOne,NULL);  //FunOne给数组赋值全为S

AfxBeginThread(FunTwo,NULL); //FunTwo也给数组赋值全为B

AfxBeginThread(GetResult,NULL);   //得到数组的值,本来期望的值为最后一次赋的值BBBB.但实际结果是不确定的,可能是SBSB,SSBB或者其它

 

UINT FunOne(LPVOID pParam){ //给数组赋值

for(int i =0; i < 4; i++){

g_charArray[i] = 'S';

Sleep(10);

}

return 0;

}

UINT FunTwo(LPVOID pParam){//得到数组值

for(int i =0; i < 4; i++){

g_charArray[i] = 'B';

Sleep(10);

}

return 0;

}

 

UINT GetResult(LPVOID pParam){//给数组赋值

szResult = CString(g_charArray);

return 0;

}

 

Win32 API中临界区(Critical Section)
为了使公共变量不会被毫无秩序,混乱的更改.我们希望一个线程使用这个变量时其他线程就不能使用,只能等别的线程用完了才用.

于是出现了临界区这说法,相当于把使用到的变量的内存看作一块区域,当某个线程使用时就进入该区域,使用完了离开.当有一个线程进入该区域时其他线程就只能在外面等.临界区的使用如下.

临界区只能用于同一个进程内的线程同步.如果想要多个进程间的线程同步就不能用它了.

 

CRITICAL_SECTION g_criSection //定义临界区变量

 

void MainTestFun{

InitializeCriticalSection(&g_criSection);  //使用前必须初始化

char g_charArray[4];

CString szResult;

AfxBeginThread(FunOne,NULL);

AfxBeginThread(FunTwo,NULL);

AfxBeginThread(GetResult,);  //此时得到的值总是BBBB或者SSSS,哪一个线程拥有临界区不确定.只能保证某一个时间只能有一个线程拥有

//DeleteCriticalSection(&g_criSection); 使用完了临界区就要删除掉,但是在这里这样使用可能会出错.因为必须保证在删除时这个临界区没有再被使用了.所以如果一个类中,一般把它放析构函数中去调用.

}

 

 

//在线程调用的函数的开始调用EnterCriticalSection结束时调用CriticalSection(&g_criSection);

//在中间有用到的所有资源在被使用时其他线程不能使用(不能读也不能改写).其它两个函数FunOne,GetResult按同样的方法添加这两行代码.这里不再写出来了.

UINT FunOne(LPVOID pParam){

EnterCriticalSection(&g_criSection); //表示进入临界区

for(int i =0; i < 4; i++){

g_charArray[i] = 'S';

Sleep(1);

}

LeaveCriticalSection(&g_criSection); //离开临界区

return 0;

}

 

MFC中的临界区类
MFC把上面的操作封装成一个类CCriticalSection,使用函数Lock与Unlock表示进入和离开临界区.上锁和解锁的说法是更符合我们的习惯思维的.

#include "afxmt.h" //需要添加该头文件引用

CCriticalSection g_criSection;

void MainTestFun{

char g_charArray[4];

CString szResult;

AfxBeginThread(FunOne,NULL);

AfxBeginThread(FunTwo,NULL);

AfxBeginThread(GetResult,); //此时得到的值总是BBBB或者SSSS,哪一个线程拥有临界区不确定.只能保证某一个时间只能有一个线程拥有 }

 

//其它两个类也同样加上这两行代码

UINT FunOne(LPVOID pParam){

g_criSection.Lock()//给所有使用的资源上锁

for(int i =0; i < 4; i++){

g_charArray[i] = 'S';

Sleep(1);

}

g_criSection.UnLock(); //给使用的资源解锁

return 0;

}

 

 

其他线程同步的方法
使线程同步共有4种方法:

1.临界区(critical section)

2.事件(event)

3.信号量(Semaphore)

4.互拆量(Mutex)

 

其中1临界区是用户对象,所以没太多权限,只能处理同一个进程内的线程同步

而剩下的2,3,4都是内核对象,权限比较大,可以跨进程使用,因此能够处理不同进程间的线程同步问题.

其中的Mutext和临界区适用的场景基本上一样,只不过Mutext是内核对象,而critical section是用户对象
--------------------- 
作者:聪明的笨蛋 
来源:CSDN 
原文:https://blog.csdn.net/weiwenhp/article/details/8650896 
版权声明:本文为博主原创文章,转载请附上博文链接!

这篇关于MFC线程(二):线程同步临界区CRITICAL SECTION的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/979360

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

java线程深度解析(六)——线程池技术

http://blog.csdn.net/Daybreak1209/article/details/51382604 一种最为简单的线程创建和回收的方法: [html]  view plain copy new Thread(new Runnable(){                @Override               public voi

java线程深度解析(五)——并发模型(生产者-消费者)

http://blog.csdn.net/Daybreak1209/article/details/51378055 三、生产者-消费者模式     在经典的多线程模式中,生产者-消费者为多线程间协作提供了良好的解决方案。基本原理是两类线程,即若干个生产者和若干个消费者,生产者负责提交用户请求任务(到内存缓冲区),消费者线程负责处理任务(从内存缓冲区中取任务进行处理),两类线程之

java线程深度解析(四)——并发模型(Master-Worker)

http://blog.csdn.net/daybreak1209/article/details/51372929 二、Master-worker ——分而治之      Master-worker常用的并行模式之一,核心思想是由两个进程协作工作,master负责接收和分配任务,worker负责处理任务,并把处理结果返回给Master进程,由Master进行汇总,返回给客

java线程深度解析(二)——线程互斥技术与线程间通信

http://blog.csdn.net/daybreak1209/article/details/51307679      在java多线程——线程同步问题中,对于多线程下程序启动时出现的线程安全问题的背景和初步解决方案已经有了详细的介绍。本文将再度深入解析对线程代码块和方法的同步控制和多线程间通信的实例。 一、再现多线程下安全问题 先看开启两条线程,分别按序打印字符串的

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

MySQL主从同步延迟原理及解决方案

概述 MySQL的主从同步是一个很成熟的架构,优点为: ①在从服务器可以执行查询工作(即我们常说的读功能),降低主服务器压力; ②在从主服务器进行备份,避免备份期间影响主服务器服务; ③当主服务器出现问题时,可以切换到从服务器。 相信大家对于这些好处已经非常了解了,在项目的部署中也采用这种方案。但是MySQL的主从同步一直有从库延迟的问题,那么为什么会有这种问题。这种问题如何解决呢? MyS

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )