C++进阶—>线程同步随笔

2023-05-16

       线程同步主要有五种方法:原子访问,临界区,信号量,事件和互斥量;其中原子访问和临界区属于用户模式的同步;信号量,事件和互斥量属于内核模式的同步。

       原子访问是通过将共享资源设置为原子变量,当一个线程访问的时候,其余的线程不得访问。C++使用临界区,信号量,事件和互斥量实现线程同步的时候,即定义相应的同步控制对象句柄,通过获取控制对象是否空闲来决定是否执行线程,若控制对象空闲则获取该对象执行线程,执行完毕后释放该控制对象,若控制对象不空闲,则等待,直到控制对象空闲并获取到控制对象后才执行线程。

       下面简单谈一谈临界区,信号量,事件和互斥量四种方法实现多线程同步或顺序执行的大体思路(理解未必深而透彻,初步理解有待提高仅作为参考)

       对于使用Windows API实现线程同步来说,只是创建了临界区或信号量或事件或互斥量控制对象,使用WaitForSingleObject函数来等待控制对象是否空闲,若空闲则获取其控制对象执行自己的线程函数,若不空闲则持续等待或等待固定时间,由于多线程是通过时间片轮转机制实现的,通过一个控制对象仅仅实现了多线程的同步(不同时访问某个资源或重复执行某条语句),但并没有实现多线程的顺序执行(即线程1、线程2、线程3....等按照顺序执行),对于多线程的顺序执行仅仅创建一个控制对象是不足以满足顺序执行,下面以事件实现三个线程顺序执行阐述:

       创建三个事件控制对象,CreatEvent event1,event2,event3;

线程1监听event1,执行完后释放event1,设置event2为有信号状态;

线程2监听event2,执行完后释放event2,设置event3为有信号状态;

线程3监听event3,执行完后释放event3,设置event1为有信号状态;

依次执行即可实现多线程的顺序执行。

/************使用临界区对象实现多线程同步***************
临界区被初始化后,当程序进入临界区后便拥有临界区的所有权,其余线程无权进入只能等对方释放临界区之后,方可进入临界区拥有其所有权再对临界区进行操作
InitializeCriticalSection()初始化临界区;
EnterCriticalSection()进入临界区;
LeaveCriticalSection()释放临界区所有权并离开临界区;
注意:上述是windows API中相关函数,CCriticalSection类是MFC中定义的临界区类,需要在MFC程序中使用(此程序为控制台程序无法使用MFC类),可以操作临界区,lock锁定临界区、unlock释放临界区
	  临界区为依次访问,不能实现其中一个线程一释放临界区就会被另一个线程访问临界区!不能实现实时监听
********************************************************/

/************使用事件对象实现多线程同步***************
事件对象是指用户在程序中使用内核对象的有无信号状态实现线程的同步临界区被初始化后,当程序进入临界区后便拥有临界区的所有权,其余线程无权进入只能等对方释放临界区之后,方可进入临界区拥有其所有权再对临界区进行操作
CreatEvent()创建并返回事件对象;
SetEvent()将指定的事件设置为有信号状态(有信号状态下其余线程可以访问);
ResetEvent()将指定的事件设置为无信号状态;
除SetEvent函数外,WaitForSingleObject函数等待指定事件。
注意:上述是Windows API函数,CEvent类是MFC实现事件对象的类
	  事件对象为立即访问,一旦事件对象被设置为有信号 立刻会被其余线程访问!能实现实时监听
********************************************************/

/************使用互斥对象实现多线程同步***************
互斥对象还可以在进程间使用,在实现线程同步时包含一个线程ID和一个计数器,线程ID表示拥有互斥对象的线程,计数器表示该互斥对象被同一线程所使用次数
CreatMutex()创建并返回互斥对象;
ReleaseMutex()释放互斥对象句柄;
WaitForSingleObject()对该对象进行请求。
注意:上述是Windows API函数,CMutex类是MFC中的互斥对象类
	  互斥对象为立即访问,一旦互斥对象被释放 立刻会被其它正在等待的线程访问!能实现实时监听
********************************************************/

/************使用信号量实现多线程同步***************
信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。
它指出了同时访问共享资源的线程 最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。
在用CreateSemaphore()创建信号量 时即要同时指出允许的最大资源计数和当前可用资源计数。
一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数 就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。
但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目, 不能在允许其他线程的进入,此时的信号量信号将无法发出。
线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可 用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。

CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,LONG lMaximumCount,LPCTSTR lpName) 创建一个信号量  
第一个参数表示安全控制,一般直接传入NULL;
第二个参数表示初始化可用资源数量;
第三个参数表示最大并发数量;
第四个参数表示信号量的名称,传入NULL表示匿名信号量。

OpenSemaphore(DWORD dwDesiredAccess,BOOL bInheritHandle,LPCTSTR lpName) 打开一个信号量  
第一个参数表示访问权限,SEMAPHORE_ALL_ACCESS要求对事件对象的完全访问;SEMAPHORE_MODIFY_STATE 允许使用ReleaseSemaphore函数;SYNCHRONIZE允许同步使用信号机对象。
第二个参数表示信号量句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。

ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount, LPLONG lpPreviousCount) 释放信号量 
第一个参数是信号量的句柄。
第二个参数表示增加个数,必须大于0且不超过最大资源数量。
第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出

注意:在CreateSemaphore创建信号量的时候如果第二个参数设置为0则表示可用的信号量资源为0,使用WaitForSingleObject函数无法获取到信号量(因为无可用的资源),此时需要调用OpenSemaphore函数打开信号量,使其可用资源为最大;
	  若不想使用OpenSemaphore函数 则在创建信号量的时候不要将初始化可用资源设置为0即可。
	  信号量机制:在信号量未达到最大并发数的时候,各线程可以同时获取信号量,直到达到了最大并发数后续线程不可再获取信号量,需要使用ReleaseSemaphore函数将当前线程的信号量释放并将信号量可用资源数+1,后续线程可获取信号量执行。
********************************************************/


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

C++进阶—>线程同步随笔 的相关文章

随机推荐

  • 【D3.js】力导向布局 + 圆形图片展示的人物关系

    前言 使用d3的力学图 xff08 力导向图 xff09 与生活中常见的人物关系图结合 xff0c 已经有了很好的例子 xff1a D3 js 进阶系列 2 0 力学图 43 人物关系图 xff0c 博主实现了下面这种样式 xff0c 已经
  • 【Android】adb 查看所有程序包名

    adb shell pm span class hljs keyword list span packages 列出所有的包名 adb shell pm list packages span class hljs label package
  • 【算法】大数乘法问题及其高效算法

    题目 编写两个任意位数的大数相乘的程序 xff0c 给出计算结果 比如 xff1a 题目描述 xff1a 输出两个不超过100位的大整数的乘积 输入 xff1a 输入两个大整数 xff0c 如1234567 和 123 输出 xff1a 输
  • 【算法】如何判断链表有环

    如何判断单链表是否存在环 有一个单向链表 xff0c 链表当中有可能出现 环 xff0c 就像题图这样 如何用程序判断出这个链表是有环链表 xff1f 不允许修改链表结构 时间复杂度O n xff0c 空间复杂度O 1 方法一 穷举遍历 方
  • 【Android】移动端接入Cronet实践

    移动端接入Cronet实践 QUIC协议获取Chromium源码编译CronetAndroid iOS buildsDesktop builds targets the current OS Running the ninja files生
  • Linux系统下安装Java环境

    目录 测试环境 下载JDK 终端模拟软件 安装前准备 tar包的安装方法 tar包的卸载 rpm包的安装方法 rpm包的卸载 测试环境 LInux系统版本 xff1a CentOS 7 64位 终端模拟软件 xff1a Xshell 6 J
  • 【Hexo】Hexo个人博客绑定域名

    Hexo个人博客绑定域名 当我们在用hexo搭建了个人博客之后 xff0c 用username github io访问难免有些奇怪 xff0c 下面就花3分钟时间对如何绑定个人域名进行描述 我这边是在阿里云买的一个域名 xff0c ycbl
  • 生产者消费者的代码实现

    当消费者获得的数据为大写字母时 xff0c 则把大写字母转换成小写字母 xff0c 并显示 xff1b 当消费者获得的数据为小写字母时 xff0c 则把小写字母转换成大写字母 xff0c 并显示 xff1b 当消费者获得的数据为字符0 1
  • 基于RobHess的SIFT图像拼接知识点随笔

    1 SIFT算法具有尺度不变性在于构建的高斯尺度空间 xff1b 2 SIFT算法具有旋转不变性在于特征方向向量 xff1b 3 K d数以图像特征点的128维特征描述子均值为依据进行划分 构建 xff1b 4 特征点匹配是一个图像的所有特
  • 最小二乘法及OpenCv函数

    1 最小二乘法 我们以最简单的一元线性模型来解释最小二乘法 什么是一元线性模型呢 xff1f 监督学习中 xff0c 如果预测的变量是离散的 xff0c 我们称其为分类 xff08 如决策树 xff0c 支持向量机等 xff09 xff0c
  • Linux服务器网络不通情况分析以及常见检查方法

    在实际运维过程中 xff0c 经常会遇到网路不通的问题 xff0c 一般此类网络不通的问题都是业务端到端的排查 本文从后端linux服务器端自查是否服务器问题 通过多年的运维经验总结 xff0c 服务器端问题导致网络不通 xff0c 大致分
  • RANSAC算法实现去除误匹配并计算拼接矩阵-随笔

    1 RANSAC算法实现去除误匹配并计算拼接矩阵流程 1 从样本集中随机抽选一个RANSAC样本 xff0c 即4个匹配点对 xff08 至少4个匹配点对 xff0c 才能计算出3 3变换矩阵 xff09 xff1b 2 计算当错误概率为0
  • linux c++ 服务器端开发面试必看书籍

    由于很多朋友希望加入到Linux c 43 43 服务器端开发的队伍中 xff0c 本人就结合自己的面试经历并整理了自己阅读的相关书籍 xff0c 同大家分享 xff0c 一起进步 人个认为以下是进入这个方向的必看书籍 xff0c 各系列难
  • C++进阶—>const、define和enum的区别和用途

    1 区别 这三种都可以定义常量 define是宏定义 xff0c 编译器不对其进行错误检查 xff0c 在预编译阶段处理 xff0c 没有作用域限制属于全局常量 xff0c 在程序中编译器会对定义的常量名以数值进行替换 xff0c 且每次替
  • MFC中基于OpenCV实现Picture Control控件成像方法

    MFC中基于OpenCV实现Picture Control控件成像方法有两种 xff0c 一种是OpenCV2 2以前版本的绘制 xff0c 另外一种是OpenCV2 2以后版本的绘制 xff08 1 xff09 在OpenCV2 2之前的
  • MFC中CFileDialog及SHBrowseForFolder

    MFC中实现通过按钮来选择文件路径或文件夹路径 xff1b xff08 1 xff09 CFileDialog类能够选择文件 xff0c 并获取其路径 xff08 当然也可以通过获取文件路径再去除文件名而获得其所在文件夹路径 xff0c 前
  • C++进阶—>带你理解多字节编码与Unicode码

    本篇文章将讲解C 43 43 开发中容易混淆的另一个概念 多字节字符集与Unicode字符集 多字节字符与宽字节字符 char与wchar t 我们知道C 43 43 基本数据类型中表示字符的有两种 xff1a char wchar t c
  • BP神经网络及其C++实现

    0 前言 神经网络在我印象中一直比较神秘 xff0c 正好最近学习了神经网络 xff0c 特别是对Bp神经网络有了比较深入的了解 xff0c 因此 xff0c 总结以下心得 xff0c 希望对后来者有所帮助 神经网络在机器学习中应用比较广泛
  • C++进阶—>Socket通信那点事

    1 网络中进程之间如何通信 xff1f 本地的进程间通信 xff08 IPC xff09 有很多种方式 xff0c 但可以总结为下面4类 xff1a 消息传递 xff08 管道 FIFO 消息队列 xff09 同步 xff08 互斥量 条件
  • C++进阶—>线程同步随笔

    线程同步主要有五种方法 xff1a 原子访问 xff0c 临界区 xff0c 信号量 xff0c 事件和互斥量 xff1b 其中原子访问和临界区属于用户模式的同步 xff1b 信号量 xff0c 事件和互斥量属于内核模式的同步 原子访问是通