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

相关文章

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Windows 上如果忘记了 MySQL 密码 重置密码的两种方法

《Windows上如果忘记了MySQL密码重置密码的两种方法》:本文主要介绍Windows上如果忘记了MySQL密码重置密码的两种方法,本文通过两种方法结合实例代码给大家介绍的非常详细,感... 目录方法 1:以跳过权限验证模式启动 mysql 并重置密码方法 2:使用 my.ini 文件的临时配置在 Wi

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

Redis在windows环境下如何启动

《Redis在windows环境下如何启动》:本文主要介绍Redis在windows环境下如何启动的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis在Windows环境下启动1.在redis的安装目录下2.输入·redis-server.exe

Pydantic中Optional 和Union类型的使用

《Pydantic中Optional和Union类型的使用》本文主要介绍了Pydantic中Optional和Union类型的使用,这两者在处理可选字段和多类型字段时尤为重要,文中通过示例代码介绍的... 目录简介Optional 类型Union 类型Optional 和 Union 的组合总结简介Pyd

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio