AutoResetEvent 是一个线程同步原语,用于在多线程环境中协调线程的执行顺序。它是.NET Framework提供的一种同步机制,用于线程间的通信和协作。
AutoResetEvent 维护了一个状态标志,可以处于有信号或无信号两种状态之一。线程可以通过等待信号或设置信号来控制自己的执行。
AutoResetEvent 具有两个主要方法:WaitOne 和 Set。以下是这些方法的功能和用法:
1. WaitOne:
- 当线程调用 WaitOne 方法时,它会进入等待状态,直到接收到信号。
- 如果 AutoResetEvent 处于无信号状态,WaitOne 方法将阻塞线程的执行。
- 如果 AutoResetEvent 处于有信号状态,WaitOne 方法将消耗该信号,并使 AutoResetEvent 重新进入无信号状态。
- 可以通过 WaitOne 的重载方法指定超时时间,在超过指定时间后,线程将继续执行而不等待信号。
2. Set:
- 当线程调用 Set 方法时,它会将 AutoResetEvent 的状态设置为有信号。
- 如果有线程正在等待信号,它将被唤醒并开始执行。
- 如果没有线程在等待信号,调用 Set 方法也会将 AutoResetEvent 的状态设置为有信号,但不会有任何其他影响。
- 即使多次调用 Set 方法,AutoResetEvent 也只会保持有信号状态一次,直到被消耗。
AutoResetEvent 的工作方式可以类比于一个门闩或红绿灯。线程可以通过等待门闩打开(WaitOne)来阻塞自己的执行,而其他线程则可以通过设置门闩打开(Set)来唤醒等待的线程。
AutoResetEvent 在多线程编程中非常有用,特别是在需要控制线程的执行顺序或实现线程间的协作时。它提供了一种简单而有效的方式来同步线程的操作,并确保线程按照期望的顺序执行。
假设有两个线程,一个线程负责生产物品,另一个线程负责消费物品。这两个线程需要进行同步,以确保在生产者生成物品后,消费者才能消费物品。
使用 AutoResetEvent 可以很方便地实现这种同步。下面是一个简单的示例代码:
using System;using System.Threading; class Program{ static AutoResetEvent producerEvent = new AutoResetEvent(false); static AutoResetEvent consumerEvent = new AutoResetEvent(true); static int item = 0; static void Main() { Thread producerThread = new Thread(ProduceItems); Thread consumerThread = new Thread(ConsumeItems); producerThread.Start(); consumerThread.Start(); producerThread.Join(); consumerThread.Join(); Console.WriteLine("Finished"); } static void ProduceItems() { for (int i = 0; i < 5; i++) { consumerEvent.WaitOne(); // 等待消费者消费物品 // 生产物品 item = i; Console.WriteLine("Produced item: " + item); producerEvent.Set(); // 发送信号给消费者 } } static void ConsumeItems() { for (int i = 0; i < 5; i++) { producerEvent.WaitOne(); // 等待生产者生产物品 // 消费物品 Console.WriteLine("Consumed item: " + item); consumerEvent.Set(); // 发送信号给生产者 } }}
在这个示例中,有一个共享的 `item` 变量表示当前要生产或消费的物品。`producerEvent` 控制生产者线程的执行,而 `consumerEvent` 控制消费者线程的执行。
生产者线程通过调用 `consumerEvent.WaitOne()` 进入等待状态,直到消费者线程消费完物品。然后,生产者线程生成一个新的物品,将其存储在 `item` 变量中,并调用 `producerEvent.Set()` 发送信号给消费者线程。
消费者线程通过调用 `producerEvent.WaitOne()` 进入等待状态,直到生产者线程生成物品。然后,消费者线程从 `item` 变量中获取物品并进行消费,并调用 `consumerEvent.Set()` 发送信号给生产者线程。
通过这种方式,生产者和消费者线程可以交替地生产和消费物品,并且彼此之间保持同步。AutoResetEvent 的使用确保了生产者和消费者线程之间的正确顺序执行,避免了竞态条件和数据不一致的问题。
在 AutoResetEvent 的构造函数中传入的参数是一个布尔值,用于指定初始的信号状态。这个参数被称为 `initialState`。
- 如果 `initialState` 为 `true`,则 AutoResetEvent 的初始状态为有信号状态。也就是说,线程在等待时不会被阻塞,而是可以直接执行。此时,调用 `WaitOne` 方法时,如果 AutoResetEvent 处于无信号状态,则线程将立即继续执行,不会等待信号。
- 如果 `initialState` 为 `false`,则 AutoResetEvent 的初始状态为无信号状态。也就是说,线程在等待时会被阻塞,直到收到信号才能继续执行。此时,调用 `WaitOne` 方法时,如果 AutoResetEvent 处于无信号状态,则线程将被阻塞,直到调用 `Set` 方法将其置为有信号状态。
可以根据实际需求来选择初始的信号状态。如果希望线程在开始时能够继续执行而不被阻塞,可以使用有信号状态;如果希望线程在开始时等待信号才能执行,可以使用无信号状态。
例如,在生产者-消费者示例中,可以使用无信号状态作为初始状态,以确保生产者线程在开始时等待消费者线程的信号才能开始生产物品。这样可以避免生产者在没有消费者消费物品时不断生成新物品。
AutoResetEvent 和 ManualResetEvent 都是线程同步原语,用于在多线程环境中协调线程的执行顺序,但它们之间有一些重要的区别。
1. 触发方式:
- AutoResetEvent:在调用 `Set` 方法后,只有一个等待线程会被唤醒并继续执行,然后 AutoResetEvent 会自动恢复为无信号状态。即每次调用 `Set` 方法只唤醒一个等待线程。
- ManualResetEvent:在调用 `Set` 方法后,所有等待线程都会被唤醒并继续执行,直到显式调用 `Reset` 方法将 ManualResetEvent 设置回无信号状态为止。即每次调用 `Set` 方法会唤醒所有等待线程。
2. 状态重置:
- AutoResetEvent:自动重置为无信号状态。即当一个线程等待信号并被唤醒后,AutoResetEvent 会自动将自身重置为无信号状态,以便下一个等待的线程能够继续等待。
- ManualResetEvent:需要显式调用 `Reset` 方法将其重置为无信号状态。即 ManualResetEvent 会保持有信号状态,直到调用 `Reset` 方法将其置回无信号状态。
3. 等待方式:
- AutoResetEvent:在调用 `WaitOne` 方法时,如果 AutoResetEvent 处于无信号状态,线程会被阻塞直到接收到信号。如果 AutoResetEvent 处于有信号状态,线程会消耗该信号并继续执行。
- ManualResetEvent:在调用 `WaitOne` 方法时,如果 ManualResetEvent 处于无信号状态,线程会被阻塞直到接收到信号。即使 ManualResetEvent 处于有信号状态,线程也会消耗该信号并继续执行,而不会自动将其重置为无信号状态。
根据这些区别,可以选择使用 AutoResetEvent 或 ManualResetEvent 来适应不同的线程同步需求。
- 如果需要每次只唤醒一个等待线程,并且希望线程在接收到信号后自动重置为无信号状态,可以使用 AutoResetEvent。这对于一些排队任务的场景很有用。
- 如果需要唤醒所有等待线程,并且希望线程在接收到信号后保持有信号状态,直到显式调用 Reset 方法将其重置为无信号状态,可以使用 ManualResetEvent。这对于一些广播通知的场景很有用。
需要根据具体的应用场景和线程同步需求来选择使用哪种同步原语。
信号同步的原理就是等待信号,有信号状态直接过,无信号就等。怎么等?通过调用WaitOnce等。Set设置信号为有信号,ReSet设置状态为无信号。AutoResetEvent就是等完之后会自动变成无信号!与之相反是ManualResetEven。
Manual翻译过来就是手动。需要显式调用 `Reset` 方法将其重置为无信号状态。
还有一个关键的问题是多个一个的区别!
我们可以的通过 同一个AutoResetEvent 对象 在不同的线程里调用很多次WaitOnce。
这样就会又很多个线程等待同一个信号,由于AutoResetEvent是自动恢复无信号的,所以只有一个等待线程会被唤醒并继续执行,那这一个线程肯定是最先调用WaitOnce的地方,因为一旦调用了WaitOnce并通过了,AutoResetEvent自动恢复无信号。其他的当然得继续等咯。
而 ManualResetEven 是手动的,所以能唤醒所有的。
原网址: 访问
创建于: 2024-06-26 18:34:44
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论