使用线程 Monitor.Wait() 和 Monitor.Pulse()
Wait() 和 Pulse() 机制用于线程间交互。当在一个对象上使用Wait() 方法时,访问这个对象的线程就会一直等待直到被唤醒。Pulse() 和 PulseAll() 方法用来通知等待的线程醒来的。下面是关于Wait() 和 Pulse() 方法如何运行的例子,WaitAndPulse.cs:
Wait() 和 Pulse() 方法仅可以在Enter() 和 Exit() 代码块内部
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Threading;
- namespace ThreadEx
- {
- public class LockMe
- {
- }
- class WaitPalsel
- {
- private int result = 0;
- private LockMe lM;
- public WaitPalsel(LockMe l)
- {
- this.lM = l;
- }
- public void CriticalSection()
- {
- Monitor.Enter(this.lM);
- Console.WriteLine("WaitPulse1: Entered Thread " + Thread.CurrentThread.GetHashCode());
- for (int i = 1; i <= 5; i++)
- {
- Monitor.Wait(this.lM);
- Console.WriteLine("WaitPulse1: Result =" + result++ + "ThreadID"
- + Thread.CurrentThread.GetHashCode());
- Monitor.Pulse(this.lM);
- }
- Console.WriteLine("WaitPulse1: Exiting Thread " + Thread.CurrentThread.GetHashCode());
- Monitor.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);
- Console.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 Exiing Thread " + Thread.CurrentThread.GetHashCode());
- Monitor.Exit(this.lM);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- LockMe l = new LockMe();
- WaitPalsel e1 = new WaitPalsel(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();
- Console.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.Wait() 和 Monitor.Pulse()的更多相关文章
- C# Monitor的Wait和Pulse方法使用详解
[转载]http://blog.csdn.net/qqsttt/article/details/24777553 Monitor的Wait和Pulse方法在线程的同步锁使用中是比较复杂的,理解稍微困难 ...
- 线程同步 – lock和Monitor
在多线程代码中,多个线程可能会访问一些公共的资源(变量.方法逻辑等等),这些公共资源称为临界区(共享区):临界区的资源是不安全,所以需要通过线程同步对多个访问临界区的线程进行控制. 同样,有些时候我们 ...
- 多线程中的lock,Monitor.Wait和Monitor.Pulse
我们知道lock实际上一个语法糖糖,C#编译器实际上把他展开为Monitor.Enter和Monitor.Exit,即: lock(lockObj) { //... } ////相当于(.Net4以前 ...
- C#的Monitor.Enter和Monitor.Exit
C#的lock 语句实际上是调用Monitor.Enter和Monitor.Exit,中间夹杂try-finally语句的简略版,下面是实际发生在之前例 子中的Go方法: 1 2 3 4 5 6 7 ...
- 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 ...
- C# 线程同步之排它锁/Monitor监视器类
一.Monitor类说明,提供同步访问对象的机制. 1.位于System.Threading命名空间下,mscorlib.dll程序集中. 2.Monitor通过获取和释放排它锁的方式实现多线程的同步 ...
- C#线程同步与死锁Monitor
在上一讲介绍了使用lock来实现C#线程同步.实际上,这个lock是C#的一个障眼法,在C#编译器编译lock语句时,将其编译成了调用Monitor类.先看看下面的C#源代码: public stat ...
- 线程基础四 使用Monitor类锁定资源
前面我们讲过了lock的用法以及竞争条件导致的错误,实际上lock关键字是Monitor类用例的一个语法糖.如果我们分解使用了lock关键字的代码,将会看到它如下面代码片段所示: bool acqui ...
- 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock
[源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...
随机推荐
- 【五校联考5day1】登山
题目 描述 题目大意 给你一个n∗nn*nn∗n的网格图.从(0,0)(0,0)(0,0)开始,每次只可以向右或向上移动一格,并且不能越过对角线(即不能为x<yx<yx<y). 网格 ...
- 【JZOJ3236】矮人排队
description 在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏.白雪公主决心终结这样的生活,所以为他们举办了体育课. 在每节课 ...
- ThinkPHP 删除数据
ThinkPHP删除数据使用delete方法,例如: 直线电机价格 $Form = M('Form'); $Form->delete(5); 表示删除主键为5的数据,delete方法可以删除单个 ...
- 【Codeforces Round #424 (Div. 2) D】Office Keys
[Link]:http://codeforces.com/contest/831/problem/D [Description] 有n个人,它们都要去一个终点,终点位于p; 但是,在去终点之前,他们都 ...
- go语言基本运算符
go语言基本运算符 1.算术运算符 以下假设A=10,B=20: 2.关系运算符 以下假设A=10,B=20: 3.逻辑运算符 以下假设A=true,B=false: 4.位运算符 十进制转二进制: ...
- CSS动画之transition属性
transition 属性 简介 transition(过渡)) 是指从一个状态到另一个状态的变化.比如当鼠标在某个元素上悬停时,我们会修改它的样式,采用 transition 可以创建一个平滑的动画 ...
- 批量插入或更新操作之ON DUPLICATE KEY UPDATE用法
实际的开发过程中,可能会遇到这样的需求,先判断某一记录是否存在,如果不存在,添加记录,如果存在,则修改数据.在INSERT语句末尾指定ON DUPLICATE KEY UPDATE可以解决这类问题. ...
- 【51nod 1874】 奇怪的数学题
题目 求 \[\sum_{i=1}^n\sum_{j=1}^nsgcd(i,j)^k\] 首先这个次大公约数显然就是\(gcd\)除一下最小质因子了 于是 \[\sum_{i=1}^n\sum_{j= ...
- PKU OJ A Bug's life
http://bailian.openjudge.cn/tm2018/G/ #include <iostream> #include <vector> #include < ...
- net.sf.json JSONObject与JSONArray使用实例
实例自己想的一个实例应用场景:一个人可以有多个角色,例如:在家中是儿子,在学校是学生,在公司是程序员,一个人还可以办好多业务 * 每个业务好多个人都可以办,则标记(mark)就是记录这唯一标识的(如i ...