关于对C#多线程类Monitor的理解
1、对线程的理解
围绕着锁周围的线程可以分为以下三类:
l 拥有锁的线程:只有一个
l 就绪队列:只有就绪队列里的线程才有机会在锁被释放时去获取锁。
l 等待队列:没有资格去获取锁。
2、Monitor.Wait(obj)方法
当线程调用 Wait 时,它释放对象的锁并进入对象的等待队列,对象的就绪队列中的下一个线程(如果有)获取锁并拥有对对象的独占使用。
Wait(obj)就是交出锁的使用权,把自己移到等待队列里,处于阻塞状态,当再次获得锁时(得先收到脉冲信号移动到就绪队列然后其他线程释放锁)返回true并且线程继续执行,否则不返回一直阻塞。
3、Monitor.Pulse方法
通知(也就是发出脉冲信号)等待队列中的线程锁定对象的状态即将发生更改。接收到脉冲后,等待线程就被移动到就绪队列中。在锁定对象被解锁后,就绪队列中的下一个线程(不一定是接收到脉冲的线程)将获得该锁。pulse()并不会使当前线程释放锁。
4、获取锁的过程
当一个线程尝试着lock一个同步对象的时候,该线程就在就绪队列中排队。一旦没人拥有该同步对象,就绪队列中的线程就可以占有该同步对象。这也是我们平时最经常用的lock方法。
为了其他的同步目的,占有同步对象的线程也可以暂时放弃同步对象,并把自己流放到等待队列中去。这就是Monitor.Wait。由于该线程放弃了同步对象,其他在就绪队列的排队者就可以进而拥有同步对象。
比起就绪队列来说,在等待队列中排队的线程更像是二等公民:他们不能自动得到同步对象,甚至不能自动移动到就绪队列。而Monitor.Pulse的作用就是开一次门,使得一个正在等待队列中的线程移动到就绪队列;相应的Monitor.PulseAll则打开门放所有等待队列中的线程到就绪队列。
5、Monitor.Wait(obj,timeOut)
阻塞自己后把自己调到等待线程,直到再次获得锁才返回继续执行。
关于该方法的一些理解分析:
l 第二个参数 tiemout表示线程释放锁进入等待队列后到进入就绪队列之前等待的一个限定时间(单位是毫秒)。
l 如果在限定时间内再次获得锁(包括收到脉冲信号然后移到就绪队列并且其他线程释放锁)就返回true然后继续运行;
l 如果在限定时间内没有收到脉冲信号,超时后,就被移到就绪队列,直到获得锁才返回,返回false;
l 如果在限定时间内收到脉冲信号,移动到就绪队列,直到获得锁才返回,返回true;
l 该方法只会在再次获得锁时才会返回,否则一直阻塞(一开始是在等待队列,最终会被移动到就绪队列);
l 建议:pulse后直接wait,中间别放其他代码。因为Monitor.Wait(obj,timeOut) 方法返回false还是true取决于在限定时间内是否收到脉冲信号从而移到就绪队列;
关于lock、线程池和定时器的简单介绍
l Lock是一个语法糖,效果相当于Monitor的TryEnter和Exit方法
l Lock锁定的对象建议是类的一个static对象,详情见 http://www.cnblogs.com/xd125/archive/2007/12/12/992406.html
l 线程池 http://www.cnblogs.com/huangxincheng/archive/2012/03/18/2405039.html
DispatcherTimer类的使用
DispatcherTimer类位于System.Windows.Threading命名空间下,类似于winform的Timer类。
{ DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += new EventHandler(timer_Tick); } void timer_Tick(object sender, EventArgs e) { tb.Text = DateTime.Now.ToLongTimeString(); } 上面的代码演示了一个简单的时钟程序,每隔一秒中更新一次时间
l