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

相关文章

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java如何通过反射机制获取数据类对象的属性及方法

《Java如何通过反射机制获取数据类对象的属性及方法》文章介绍了如何使用Java反射机制获取类对象的所有属性及其对应的get、set方法,以及如何通过反射机制实现类对象的实例化,感兴趣的朋友跟随小编一... 目录一、通过反射机制获取类对象的所有属性以及相应的get、set方法1.遍历类对象的所有属性2.获取

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象