Wait() 和 Pulse() 机制用于线程间交互。当在一个对象上使用Wait() 方法时,访问这个对象的线程就会一直等待直到被唤醒。Pulse() 和 PulseAll() 方法用来通知等待的线程醒来的。下面是关于Wait() 和 Pulse() 方法如何运行的例子,WaitAndPulse.cs:

Wait() 和 Pulse() 方法仅可以在Enter() 和 Exit() 代码块内部调用。

/*************************************
/* Copyright (c) 2012 Daniel Dong* * Author:Daniel Dong* Blog:  www.cnblogs.com/danielWise* Email: guofoo@163.com* */using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;namespace WaitAndPulse
{public class LockMe{ }class WaitPulse1{private int result = 0;private LockMe lM;public WaitPulse1(){}public WaitPulse1(LockMe l){this.lM = l;}public void CriticalSection(){Monitor.Enter(this.lM);//Enter the Critical SectionConsole.WriteLine("WaitPulse1: Entered Thread "+ Thread.CurrentThread.GetHashCode());for (int i = 1; i <= 5; i++){Monitor.Wait(this.lM);Console.WriteLine("WaitPulse1: WokeUp");Console.WriteLine("WaitPulse1: Result = "+ result+++ " ThreadID "+ Thread.CurrentThread.GetHashCode());Monitor.Pulse(this.lM);}Console.WriteLine("WaitPulse1: Exiting Thread "+ Thread.CurrentThread.GetHashCode());//Exit the Critical SectionMonitor.Exit(this.lM);}}class WaitPulse2{private int result = 0;private LockMe lM;public WaitPulse2(){}public WaitPulse2(LockMe l){this.lM = l;}public void CriticalSection(){Monitor.Enter(this.lM);//Enter the Critical SectionConsole.WriteLine("WaitPulse2: Entered Thread "+ Thread.CurrentThread.GetHashCode());for (int i = 1; i <= 5; i++){Monitor.Pulse(this.lM);Console.WriteLine("WaitPulse2: Result = "+ result+++ " ThreadID "+ Thread.CurrentThread.GetHashCode());Monitor.Wait(this.lM);Console.WriteLine("WaitPulse2: WokeUp");}Console.WriteLine("WaitPulse2: Exiting Thread "+ Thread.CurrentThread.GetHashCode());//Exit the Critical SectionMonitor.Exit(this.lM);}}public class ClassForMain{public static void Main(string[] args){LockMe l = new LockMe();WaitPulse1 e1 = new WaitPulse1(l);WaitPulse2 e2 = new WaitPulse2(l);Thread t1 = new Thread(new ThreadStart(e1.CriticalSection));t1.Start();Thread t2 = new Thread(new ThreadStart(e2.CriticalSection));t2.Start();//Wait till the user enters somethingConsole.ReadLine();}}
}

输出结果如下:

在Main() 方法中,我们创建了一个LockMe对象。然后创建了两个对象,WaitPulse1, WaitPulse2, 接着把它们委托给线程以便于线程可以调用这两个对象的CriticalSection()方法。注意WaitPulse1和WaitPulse2这两个对象中的LockMe实例是不同的,因为传递给对应构造函数的对象引用不同。初始化完对象以后,我们创建了两个线程t1 和 t2, 并向这两个线程分别传递各自的CriticalSection()函数。

假设WaitPulse1.CriticalSection() 先执行,线程t1 进入方法的关键部分并在锁住LockMe对象后在for循环中执行Monitor.Wait()。由于执行了Monitor.Wait(), 所以它得等待其他线程调用Monitor.Pulse()方法(一个运行时通知)来将其唤醒。我们锁住LockMe对象是因为我们只希望在任意时间仅有一个对象访问共享LockMe实例。

注意当线程执行Monitor.Wait()方法时,它会暂时释放LockMe对象上的锁,这样其他线程就可以访问LockMe对象。在线程t1进入等待状态后,线程t2可以自由地访问LockMe对象。尽管这两个线程都有自己的LockMe对象(WaitPulse1, WaitPulse2),但是它们都引用同一个对象。线程t2获得LockMe对象上的锁并进入WaitPulse2.CriticalSection()方法。当它进入for循环时,它给等待LockMe对象的线程(本例中是t1)发送一个运行时通知(Monitor.Pulse())然后进入等待状态。

最终,t1醒来并获得LockMe对象的锁。线程t1然后访问result变量并向等待LockMe对象的线程(本例中为t2)发送一个运行时通知。如此反复直到for循环结束。

如果你依据程序的输出结果来看上面的描述,那么我们说的概念会非常清晰易懂。要注意每个Enter()方法都有一个Exit()方法匹配否则程序不应该结束。

Enter()方法接受一个对象作为参数。如果参数为null 或者参数时一个方法名或者一个值类型的对象(比如int型),Enter()方法都会抛出异常。

下一篇将会介绍Monitor.TryEnter() 方法 和 Lock 语句…

C# 线程手册 第三章 使用线程 Monitor.Wait() 和 Monitor.Pulse()相关推荐

  1. C# 线程手册 第三章 使用线程 实现一个数据库连接池(实战篇)

    在企业级软件开发过程中,为了改善应用程序的性能需要通常使用对象池来控制对象的实例化.例如,在我们每次需要连接一个数据库时都需要创建一个数据库连接,而数据库连接是非常昂贵的对象.所以,为了节省为每次数据 ...

  2. C# 线程手册 第三章 使用线程

    概要 在之前章节,我们已经讨论过线程在开发多用户应用程序时扮演的重要角色.我们已经使用线程来解决一些重要的问题,比如让多个用户或者客户端在同一时间访问同一个资源.然而,在学习过程中我们忽略了一个问题, ...

  3. C# 线程手册 第三章 使用线程 Monitor.TryEnter()

    Monitor 类的TryEnter() 方法在尝试获取一个对象上的显式锁方面和 Enter() 方法类似.然而,它不像Enter()方法那样会阻塞执行.如果线程成功进入关键区域那么TryEnter( ...

  4. Java7并发编程指南——第三章:线程同步辅助类

    Java7并发编程指南--第三章:线程同步辅助类 @(并发和IO流) Java7并发编程指南第三章线程同步辅助类 思维导图 项目代码 思维导图 项目代码 GitHub:Java7Concurrency ...

  5. C# 线程手册 第四章 线程设计原则 对等线程模型

    我们将要描述的下一个线程模型是对等线程模型.在这个线程模型中,每个线程都会从合适的源接收它自己的输入并对应地处理.这个模型在图4中做了描述. 图 4 在上面的图片中,UI 线程将根据键盘和鼠标的输入进 ...

  6. MySQL 5.6 手册 第三章 目录

    Chapter 3 Tutorial 第三章 辅导教程 Table of Contents 目录   3.1 Connecting to and Disconnecting from the Serv ...

  7. 线程学习(三):线程的互斥

    线程互斥 生产者与消费者模型 为什么需要线程同步和互斥 线程互斥 没有线程互斥会怎么样 mutex(互斥量) 互斥量接口 互斥量初始化有两种方式 互斥量销毁 互斥量的加锁和解锁 死锁 互斥锁使用步骤 ...

  8. Android 渗透测试学习手册 第三章 Android 应用的逆向和审计

    第三章 Android 应用的逆向和审计 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 在本章中,我们将查看 Android 应用程序或.apk文件,并了解其不同的 ...

  9. Java基础 - 坦克大战(第三章,线程基础与线程使用)

    文章目录 本章内容 - 多线程处理 绘制敌方坦克 线程基础 线程相关概念 程序(program) 进程 什么是线程 其他相关概念 单线程 多线程 并发 并行 获取当前电脑处理器(cpu)个数 Java ...

  10. C# 线程手册 第五章 扩展多线程应用程序 系列

    [第1篇] 什么是线程池 到目前为止我们使用多线程应用程序的目的是尽可能多地使用计算机处理器资源.所以,看起来我们仅需要为每个独立的任务分配一个不同的线程,并让处理器确定在任何时间它总会处理其中的某一 ...

最新文章

  1. 机器学习面试题集-图解准确率,精确率,召回率
  2. 71岁的亿万富翁坐自家飞船成功游览太空!此前已为太空旅行砸了超10亿美元
  3. 一致性哈希算法学习及JAVA代码实现分析
  4. 递归应用场景和调用机制
  5. 微机原理与接口耿恒山答案_KYN28-12柜二次系统元器件介绍及接线应用原理(接上篇)...
  6. javaScript书写规范
  7. Android闹钟设置的解决方案
  8. 历届电大计算机网考试题及答案,电大2012年计算机应用基础网考统考试题及答案...
  9. 一文掌握 Linux 性能分析之 CPU 篇
  10. [恢]hdu 2206
  11. 博图注册表删除方法_「博图+仿真+授权」西门子软件安装指南及注意事项
  12. Java 使用谷歌翻译免费api,翻译文档
  13. 涉案金额2亿多!贺金虎、刘国庆非法吸收公众存款案开庭
  14. vue-cli脚手架中使用talkingData埋点的方法
  15. 「黑科技」盘点那些脑洞大开的人类设计的“异形”机器人
  16. 基于STM32平台的数字温度显示器系统设计
  17. 第46讲 Android Camera2 API AWB自动白平衡
  18. java gef_GEF最简单的入门-helloword(1)
  19. 图像处理:高斯滤波算法
  20. 怎样找到ant压缩这个软件_PDF压缩到最小该怎么完成?这个PDF压缩软件最实用

热门文章

  1. catia 创成钣金设计_应用Inventor进行钣金设计
  2. 计算机科学导论教程,计算机科学导论教程重点(6页)-原创力文档
  3. Python爬虫入门学习线路图2019最新版
  4. Python Tornado web框架简单例子
  5. Go常用功能总结一阶段
  6. 手把手教你编写-微信机器人
  7. Java千百问_05面向对象(008)_java中覆盖是什么
  8. 从mysql中检索数据后,通过userId的链接去delete数据
  9. 2月中国万网域名总量净增2.1万个 份额突破24%
  10. Apache/MySQL/PHP 集体升级