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

这篇具有很好参考价值的文章主要介绍了关于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());

关于C#中Monitor的wait/pulse的理解,C#,语法,开发语言,c#

首先线程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());

关于C#中Monitor的wait/pulse的理解,C#,语法,开发语言,c#

说明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不能跨越应用程序域和进程使用。

  • 必须通过锁保护所有信号同步逻辑涉及的变量。文章来源地址https://www.toymoban.com/news/detail-799776.html

到了这里,关于关于C#中Monitor的wait/pulse的理解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言中关于指针的理解及用法

    关于指针意思的参考: https://baike.baidu.com/item/%e6%8c%87%e9%92%88/2878304   指针 = 指针变量 = 地址  野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的) 以下是导致野指针的原因  在这里面*p没有初始化,所以默认为随机值,我们也把这样的指针叫做野指

    2024年01月16日
    浏览(30)
  • 关于云计算的个人理解_谈谈对云计算的理解,大数据开发面试相关文章及Github学习资料

    (5) 高可扩展性 “云”的规模可以动态伸缩,满足应用和用户规模增长的需要。 (6) 按需服务 “云”是一个庞大的资源池,你按需购买;云可以像自来水,电,煤气那样计费。 (7) 极其廉价 由于“云”的特殊容错措施可以采用极其廉价的节点来构成云,“云”的自动化集中式

    2024年04月17日
    浏览(33)
  • 【鸿蒙开发】第七章 ArkTS语言UI范式-基础语法

    通过前面的章节,我们基本清楚鸿蒙应用开发用到的语言和项目基本结构,在【鸿蒙开发】第四章 Stage应用模型及项目结构也提到过ArkTS的UI范式的 基本语法 、 状态管理 、 渲染控制 等能力,简要介绍如下: 基本语法 : ArkTS 定义了 声明式UI描述 、 自定义组件 和 动态扩展

    2024年02月03日
    浏览(46)
  • HarmonyOS/OpenHarmony应用开发-ArkTS语言基本语法说明

    图1  示例效果图   本示例中,ArkTS的基本组成如下所示。 图2  ArkTS的基本组成     装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中@Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组

    2024年02月07日
    浏览(44)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 二)

    在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成

    2024年02月04日
    浏览(43)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 一)

    ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在 TypeScript (简称 TS )生态基础上做了进一步扩展,继承了 TS 的所有特性,是 TS 的超集。因此,在学习 ArkTS 语言之前,建议开发者具备 TS 语言开发能力。 当前, ArkTS 在 TS 的基础上主要扩展了如下能力: 基本语法:

    2024年02月16日
    浏览(46)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 五)

    如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。 @Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位

    2024年02月17日
    浏览(43)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 四)

    当创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量

    2024年02月17日
    浏览(41)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 三)

    在开始之前,先明确自定义组件和页面的关系: 自定义组件: @Component 装饰的 UI 单元,可以组合多个系统组件实现 UI 的复用。 页面:即应用的 UI 页面。可以由一个或者多个自定义组件组成, @Entry 装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有

    2024年02月16日
    浏览(43)
  • HarmonyOS(二)—— 初识ArkTS开发语言(下)之ArkTS声明式语法和组件化基础

    通过前面ArkTS开发语言(上)之TypeScript入门以及ArkTS开发语言(中)之ArkTS的由来和演进俩文我们知道了ArkTS的由来以及演进,知道了ArkTS具备了声明式语法和组件化特性,今天,搭建一个可刷新的排行榜页面。在排行榜页面中,使用循环渲染控制语法来实现列表数据渲染,使

    2024年02月04日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包