关于C#中Monitor的wait/pulse的理解

wait:表示释放对象上的锁并阻止当前线程,直到它重新获取该锁。

pulse:表示通知等待队列中的线程锁定对象状态的更改。

当线程调用 Wait 时,它会释放对象上的锁并进入对象的等待队列。 对象的就绪队列中的下一个线程 (如果有一个) 获取锁并独占使用该对象。 调用 Wait 的所有线程都保留在等待队列中,直到它们收到来自 Pulse 或 PulseAll 的信号,由锁的所有者发送。 如果 Pulse 发送 ,则只会影响等待队列头部的线程。 如果 PulseAll 发送 ,则等待对象的所有线程都会受到影响。 收到信号后,一个或多个线程离开等待队列并进入就绪队列。 允许就绪队列中的线程重新获取锁。

实例1:Wait(object);    

 public class MonitorTest{private object _lock = new object();public void FuncA(){lock (_lock){Console.WriteLine("进入函数A");Monitor.Wait(_lock);Console.WriteLine("退出函数A");}}public void FuncB(){Thread.Sleep(300);lock (_lock){Console.WriteLine("进入函数B");Thread.Sleep(3000);Monitor.Pulse(_lock);Thread.Sleep(3000);Console.WriteLine("退出函数B");}}}调用:MonitorTest monitorTest = new MonitorTest();
Task.Run(() => monitorTest.FuncA());
Task.Run(() => monitorTest.FuncB());

首先线程A通过wait方法释放锁,让线程B获取锁后成功开始执行,线程A进入等待队列,线程B执行过程中不再需要锁定对象后,则会调用pulse发送释放锁的信号,让收到信号的线程A从等待队列进入就绪队列,当线程B执行完成释放锁后,线程A重新获得锁,继续执行。

可以看到在线程B中发出Pulse信号后,线程A收到信号,进入就绪队列,此时线程B还没有释放锁,直到线程完成3s等待后,线程A才重新获取锁,wait(object)才返回。

说明1:发出pulse信号并不是释放锁,只是给等待队列中发送一个信号,收到信号的等待线程就会移动到就绪队列。

说明2:收到信号的Wait(object);不会立即返回,必须等到重新获取到锁后,才会返回,继续往下执行。如果收不到pulse信号,此等待将无限期的等待下去。

实例2:wait(object, int32);

此函数会在指定的时间内等待信号,如果超时则会自动进入就绪线程。当重新获取锁返回后,返回值为fasle.表示未在指定时间内获取锁,否则返回true.

public class MonitorTest
{private object _lock = new object();public void FuncA(){lock (_lock){Console.WriteLine("进入函数A");bool flag = false;while (!flag){flag = Monitor.Wait(_lock, 1000);Console.WriteLine("是否真实信号:" + flag);}Console.WriteLine("是否真实信号:" + flag);Console.WriteLine("退出函数A");}}public void FuncB(){Thread.Sleep(300);lock (_lock){Console.WriteLine("进入函数B");Thread.Sleep(3000);//Monitor.Pulse(_lock);Console.WriteLine("退出函数B");}}}调用:
MonitorTest monitorTest = new MonitorTest();
Task.Run(() => monitorTest.FuncA());
Task.Run(() => monitorTest.FuncB());

说明1:这里我们在线程B中,并没有发出pulse信号,线程也没有无限期等待。

说明2:如果我们在2s超时前,在线程B中发送pulse信号,则返回值为true.

说明3:无论我们发不发信号,线程A必须在线程B释放锁后,重新获得锁才会返回,继续执行,跟wait(object)一致。

如果超时时间设置为Timeout.Infinite,这与wait(object)一样,如果设置为0,则立即释放锁,进入就绪队列。

使用Wait/Pulse需要注意:

  • Wait / Pulse不能lock块之外使用,否则会抛异常。
  • Pulse最多释放一个线程,而PulseAll释放所有线程。
  • Wait会立即释放当前持有的锁,然后进入阻塞,等待脉冲
  • 收到脉冲会立即尝试重新获取锁,如果在指定时间内重新获取,则返回true,如果在超过指定时间获取,则返回false,如果没有获取锁,则一直阻塞不会返回

性能方面,调用Pulse花费大概约是在等待句柄上调用Set三分之一的时间。但是,使用WaitPulse进行信号同步,对比事件等待句柄有以下缺点:

  • Wait / Pulse不能跨越应用程序域和进程使用。

  • 必须通过锁保护所有信号同步逻辑涉及的变量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/410382.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

导入失败,报错:“too many filtered rows xxx, “ErrorURL“:“

一、问题: 注:前面能正常写入,突然就报错,导入失败,报错:“too many filtered rows xxx, "ErrorURL":" {"TxnId":769494,"Label":"datax_doris_writer_bf176078-…

【嘉立创EDA-PCB设计指南】3.网络表概念解读+板框绘制

前言:本文对网络表概念解读板框绘制(确定PCB板子轮廓) 网络表概念解读 在本专栏的上一篇文章【嘉立创EDA-PCB设计指南】2,将设计的原理图转为了PCB,在PCB界面下出现了所有的封装,以及所有的飞线属性&…

AI大模型预先学习笔记二:prompt提问大模型、langchain使用大模型框架、fine tune微调大模型

文章目录 一、Prompt Engineering(怎么去提问大模型)1)环境准备2)交互代码的参数备注3)交互代码 二、LangChain(一个框架去使用大模型)1)LangChain核心介绍:I/O模块、数据…

231012期高薪就业榜来啦!就业班平均就业薪资8065元!就业路上,优橙与你并肩同行!!

承诺一定会抵达,无远弗届。231012期优橙就业薪资榜来啦!! 231012期,平均就业薪资8065元,彰显优橙的就业底气!! 231012期,最高就业薪资10000元,明晰学员的就业实力&…

《C++入门篇》——弥补C不足

文章目录 前言一.命名空间二.缺省参数三.函数重载四.引用4.1引用做参数4.2引用做返回值 五.内联函数六.小语法6.1auto6.2范围for6.3空指针 前言 C是业内一门久负盛名的计算机语言,从C语言发展起来的它,不仅支持C语言的语法,还新添加了面向对…

LLM漫谈(三)| 使用Chainlit和LangChain构建文档问答的LLM应用程序

一、Chainlit介绍 Chainlit是一个开源Python包,旨在彻底改变构建和共享语言模型(LM)应用程序的方式。Chainlit可以创建用户界面(UI),类似于由OpenAI开发的ChatGPT用户界面,Chainlit可以开发类似…

MongoDB认证考试小题库

Free MongoDB C100DBA Exam Actual Questions 关于MongoDB C100 DBA 考试真题知识点零散整理 分片架构 应用程序 --> mongos --> 多个mongod对于应用来说,连接分片集群跟连接一台单机mongod服务器一样分片好处, 增加可用RAM、增加可用磁盘空间、…

Js-web APIs(一)

目录 Web API 基本认知 • 作用和分类 • 什么是DOM • DOM树 • DOM对象(重要) 获取DOM对象 • 根据CSS选择器来获取DOM元素 (重点) 1.选择匹配的第一个元素 2.选择匹配的多个元素 • 其他获取DOM元素方法(了解) 操作元素内容 • 对象.innerT…

二十几种未授权访问漏洞合集

未授权访问漏洞是一个在企业内部非常常见的问题,这种问题通常都是由于安全配置不当、认证页面存在缺陷,或者压根就没有认证导致的。当某企业对外的服务端口、功能无限制开放,并且对用户的访问没有做任何限制的时候,可能会泄露出某…

Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战

文章目录 PreCode基础工程启动类切入口事件 发布事件同步 Listener异步Listener增加EnableAsync增加 Async 测试 Pre Spring Boot - Application Events 的发布顺序_ApplicationStartingEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEv…

Centos7 安装与卸载mysql

卸载 ps ajx | grep mysql : 查看当前服务器是否有mysql 没有的话就不需要卸载咯。 centos7 通过yum下载安装包通常是以.rpm为后缀,rpm -qa 可以查看当前服务器上所有的安装包: rpm -qa | grep mysql | xargs yum -y remove :将查询到的mysql…

JavaScript 学习笔记(Day1)

「写在前面」 本文为 b 站黑马程序员 pink 老师 JavaScript 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。 目录 1 课程介绍 2 课程软件准备工作 3 JavaScript 介绍 4 变量 5 常量 6 数据类型 7 类型转换 8 实战案…