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

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Threading;
  7. namespace ThreadEx
  8. {
  9. public class LockMe
  10. {
  11. }
  12. class WaitPalsel
  13. {
  14. private int result = 0;
  15. private LockMe lM;
  16. public WaitPalsel(LockMe l)
  17. {
  18. this.lM = l;
  19. }
  20. public void CriticalSection()
  21. {
  22. Monitor.Enter(this.lM);
  23. Console.WriteLine("WaitPulse1: Entered Thread " + Thread.CurrentThread.GetHashCode());
  24. for (int i = 1; i <= 5; i++)
  25. {
  26. Monitor.Wait(this.lM);
  27. Console.WriteLine("WaitPulse1: Result =" + result++ + "ThreadID"
  28. + Thread.CurrentThread.GetHashCode());
  29. Monitor.Pulse(this.lM);
  30. }
  31. Console.WriteLine("WaitPulse1: Exiting Thread " + Thread.CurrentThread.GetHashCode());
  32. Monitor.Exit(this.lM);
  33. }
  34. }
  35. class WaitPulse2
  36. {
  37. private int result = 0;
  38. private LockMe lM;
  39. public WaitPulse2()
  40. { }
  41. public WaitPulse2(LockMe l)
  42. {
  43. this.lM = l;
  44. }
  45. public void CriticalSection()
  46. {
  47. Monitor.Enter(this.lM);
  48. Console.WriteLine("WaitPulse2: Entered Thread " + Thread.CurrentThread.GetHashCode());
  49. for (int i = 1; i < 5; i++)
  50. {
  51. Monitor.Pulse(this.lM);
  52. Console.WriteLine("WaitPulse2: Result ="+result++ +"ThreadID"
  53. +Thread.CurrentThread.GetHashCode());
  54. Monitor.Wait(this.lM);
  55. Console.WriteLine("WaitPulse2: WokeUp");
  56. }
  57. Console.WriteLine("WaitPulse2 Exiing Thread " + Thread.CurrentThread.GetHashCode());
  58. Monitor.Exit(this.lM);
  59. }
  60. }
  61. class Program
  62. {
  63. static void Main(string[] args)
  64. {
  65. LockMe l = new LockMe();
  66. WaitPalsel e1 = new WaitPalsel(l);
  67. WaitPulse2 e2 = new WaitPulse2(l);
  68. Thread t1 = new Thread(new ThreadStart(e1.CriticalSection));
  69. t1.Start();
  70. Thread t2 = new Thread(new ThreadStart(e2.CriticalSection));
  71. t2.Start();
  72. Console.ReadLine();
  73. }
  74. }
  75. }

在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.Wait() 和 Monitor.Pulse()的更多相关文章

  1. C# Monitor的Wait和Pulse方法使用详解

    [转载]http://blog.csdn.net/qqsttt/article/details/24777553 Monitor的Wait和Pulse方法在线程的同步锁使用中是比较复杂的,理解稍微困难 ...

  2. 线程同步 – lock和Monitor

    在多线程代码中,多个线程可能会访问一些公共的资源(变量.方法逻辑等等),这些公共资源称为临界区(共享区):临界区的资源是不安全,所以需要通过线程同步对多个访问临界区的线程进行控制. 同样,有些时候我们 ...

  3. 多线程中的lock,Monitor.Wait和Monitor.Pulse

    我们知道lock实际上一个语法糖糖,C#编译器实际上把他展开为Monitor.Enter和Monitor.Exit,即: lock(lockObj) { //... } ////相当于(.Net4以前 ...

  4. C#的Monitor.Enter和Monitor.Exit

    C#的lock 语句实际上是调用Monitor.Enter和Monitor.Exit,中间夹杂try-finally语句的简略版,下面是实际发生在之前例 子中的Go方法: 1 2 3 4 5 6 7 ...

  5. Benchmark result without MONITOR running: Benchmark result with MONITOR running (redis-cli monitor > /dev/null): 吞吐量 下降约1半 Redis监控工具,命令和调优

    https://redis.io/commands/monitor In this particular case, running a single MONITOR client can reduc ...

  6. C# 线程同步之排它锁/Monitor监视器类

    一.Monitor类说明,提供同步访问对象的机制. 1.位于System.Threading命名空间下,mscorlib.dll程序集中. 2.Monitor通过获取和释放排它锁的方式实现多线程的同步 ...

  7. C#线程同步与死锁Monitor

    在上一讲介绍了使用lock来实现C#线程同步.实际上,这个lock是C#的一个障眼法,在C#编译器编译lock语句时,将其编译成了调用Monitor类.先看看下面的C#源代码: public stat ...

  8. 线程基础四 使用Monitor类锁定资源

    前面我们讲过了lock的用法以及竞争条件导致的错误,实际上lock关键字是Monitor类用例的一个语法糖.如果我们分解使用了lock关键字的代码,将会看到它如下面代码片段所示: bool acqui ...

  9. 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock

    [源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...

随机推荐

  1. MYSQL批量创建表的存储过程

    因为业务需要,创建了100个表,但是这些表的结构都是一样的,作为程序员,就是要解决这种重复劳动.然而这种事情还要单独写个php脚本的话太麻烦了吧,所以就干脆学了一下直接用Mysql存储过程怎么实现: ...

  2. memcache课程---4、php+memcache如何让用户跨域登录

    memcache课程---4.php+memcache如何让用户跨域登录 一.总结 一句话总结: 让所有服务器共用一台memcache缓存,即可达到跨域的目的 1.session跨域:修改php配置文 ...

  3. iOS之CATiledLayer的属性简介和使用

    1.CATiledLayer简介 CATiledLayer用于大型图片进行分割显示,需要显示的图片才会加载,直接上代码: - (void)viewDidLoad { [super viewDidLoa ...

  4. PAT甲级——A1096 Consecutive Factors【20】

    Among all the factors of a positive integer N, there may exist several consecutive numbers. For exam ...

  5. jun引导1.04可以让N3050支持6.2

    1.03引导用在3050可以安装 但是安装后找不到dsm 需要手动插拔电源才可以解决 偶尔还会死机 1.04可以引导3050安装6.2 23739 安装24922正常,但是moments传照片后会死机 ...

  6. js时间操作getTime(),ios移动端真机上返回显示NAN

    ios移动端,js时间操作getTime(),getFullYear()等返回显示NaN的解决办法及原因 在做移动端时间转化为时间戳时,遇到了一个问题,安卓手机上访问时,能拿到时间戳,从而正确转换时间 ...

  7. Windows API 第19篇 FindFirstVolumeMountPoint FindNextVolumeMountPoint

    相关函数:HANDLE FindFirstVolumeMountPoint(                                                               ...

  8. There is no public key available for the following key IDs:3B4FE6ACC0B21F32

    ubuntu 运行完sudo apt-get update之后,提示 W: There is no public key available for the following key IDs: 3B ...

  9. fcc筆記

    在 JavaScript 中所有的变量都是大小写敏感的JavaScript提供七种不同的data types(数据类型),它们是undefined(未定义), null(空), boolean(布尔型 ...

  10. 利用animate.css和es6制作文字向上滚动的效果

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel= ...