Windows支持的4种类型的同步对象:临界区、互斥量、事件和信号量

2024-01-07 17:48

本文主要是介绍Windows支持的4种类型的同步对象:临界区、互斥量、事件和信号量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    Windows支持4种类型的同步对象,可以用来同步由并发运行的线程所执行的操作:

  • 临界区
  • 互斥量
  • 事件
  • 信号量

    MFC在名为CCriticalSection、CMutex、CEvent和CSemaphore的类中封装了这些对象。下面分别对这些同步对象进行介绍。

  • 临界区

    最简单类型的线程同步对象就是临界区。临界区用来串行化对由两个或者多个线程共享的资源的访问。这些线程必须属于相同的进程,因为临界区不能跨越进程的边界工作。

    临界区背后的思想就是,每个独占性地访问一个资源的线程可以在访问那个资源之前锁定临界区,访问完成之后解除锁定。如果线程B试图锁定当前线程A锁定的临界区,线程B将阻塞直到该临界区空闲。阻塞时,线程B处在一个十分有效的等待状态,它不消耗处理器时间。

  • 互斥量

    Mutex是单词mutually和exclusive的缩写。与临界区一样,互斥量也是用来获得对由两个或者更多线程共享的资源的独占性访问的。与临界区不同的是,互斥量可以用来同步在相同进程或者不同进程上运行的线程。对于进程内线程同步的需要,临界区一般要优于互斥量,因为临界区更快,但是如果希望同步在两个或者多个不同进程上运行的线程,那么互斥量就更合适了。

    互斥量和临界区还有另外有一个差别。如果一个线程锁定了临界区而终止时没有解除临界区的锁定,那么等待临界区空闲的其他线程将无限期地阻塞下去。然而,如果锁定互斥量的线程不能在其终止前解除互斥量的锁定,那么系统将认为互斥量被“放弃”了,并自动释放该互斥量,这样等待进程就可以继续进行。

  • 事件

    MFC的CEvent类封装了Win32事件对象。一个事件不只是操作系统内核中的一个标记。在任何特定的时间,事件只能处在两种状态中的一种:设置或者重置。设置状态事件也可以认为是处于信号状态,重置状态事件也可以认为是处于非信号状态。CEvent::SetEvent设置一个事件,而CEvent::ResetEvent将事件重置。相关函数CEvent::PulseEvent可以在一次操作中设置和清除一个事件。

    有时事件被描述为“线程触发器”。一个线程调用CEvent::Lock在一个事件上阻塞,等待该事件变为设置状态。另一个线程设置事件,从而唤醒该等待线程。设置事件就像按下触发器。它解除等待线程的阻塞并允许该线程继续执行。一个事件可能有一个或者多个在事件上阻塞的线程,如果你的代码正确,那么当该事件变为设置状态时,所有的等待线程都将被唤醒。

    Windows支持两种不同类型的事件:自动重置事件手动重置事件。它们之间的差别非常细微,但其意义却是深远的。当在自动重置事件上阻塞的线程被唤醒时,该事件被自动重置为信号状态。手动重置事件不能自动重置,它必须使用编程方式重置。用于选择自动重置事件还是手动重置事件——以及一旦做出选择之后如何使用它们——的规则如下:

    1) 如果事件只触发一个线程,那么使用自动重置事件和使用SetEvent唤醒等待线程。这里不需要调用ResetEvent,因为线程被唤醒那一刻事件将自动重置。

    2) 如果事件将触发两个或者多个线程,那么使用手动重置线程和使用PulseEvent唤醒所有的等待线程。而且,不需要调用ResetEvent,因为PulseEvent在唤醒线程后将重置事件。

    使用手动重置事件来触发多个线程是至关重要的。为什么?因为自动重置事件将在其中一个线程被唤醒的那一刻被重置,因此它只触发一个线程。使用PulseEvent来按下手动重置事件上的触发器也是相当重要的。如果使用SetEvent和ResetEvent,就有保证所有的等待线程都被唤醒。PulseEvent不仅能够设置和重置事件,而且还确保了所有在事件上等待的线程在重置事件之前被唤醒。

    与互斥量一样,事件可以用来协调在不同进程上运行的线程,对于跨越进程边界的事件,必须给它指定一个名称。

    那么,怎样使用事件来同步线程呢?例如,线程A向缓冲区填充数据,而线程B需要对缓冲区的数据进行处理。假定线程B必须等待来自线程A的一个信号(缓冲区已初始化并准备工作)。这时,自动重置事件是完成这项工作的绝好工具。

    自动重置事件适用于触发单线程,但如果与线程B平行的线程对C缓冲的数据进行了完全不同的操作,那会怎么样呢?这就需要手动重置事件一同唤醒线程B和C,因为自动重置事件只能唤醒其中的一个或者另一个,而不能都唤醒 。

    再次重申,自动重置事件和CEvent::SetEvent释放在事件上阻塞的单个线程,手动重置事件和CEvent::PulseEvent释放多个线程。

  • 信号量

    最后一种同步化对象是信号量。如果任何一个线程锁定了事件、临界区和互斥对象,Lock就会阻塞它们,在这个意义上,这3种对象具有这样的特性:”要么有,要么什么都没有“。信号量则不同,它始终保存有可用资源数量的资源数。锁定信号量会减少资源数,释放信号量则增加资源数。只有在线程试图锁定资源数为0的信号量时,线程才会被阻塞。在这种情况下,直到另一个线程释放信号量,资源数随之增加时,或者直到指定的超时时间期满时,该线程才会被释放。信号量可以用来同步同一进程中的线程,也可以同步不同进程中的线程。





这篇关于Windows支持的4种类型的同步对象:临界区、互斥量、事件和信号量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal