多线程一直在学习和理解中......
Monitor类是多线程中用以实现同步的一种技术,主要是同一进程内多线程间的同步技术。
Monitor类中有以下几个方法需要注意:
Monitor.Enter(object obj)方法,其意义相当于Lock(obj);
Monitor.Exit(object obj)方法,意思是释放被锁的对象
Monitor.Wait(object obj)方法,释放被锁的对象,并阻塞当前线程,等待其他线程通知(Pulse)再次获得锁 (个人理解 当前线程 锁 自己也阻塞了 要其他线程唤醒)
Monitor.Pulse(object obj)方法,通知等待加锁obj的线程解除阻塞,obj对象状态已经改变(个人理解 唤醒锁住线程 这样锁住线程继续执行 当前方法也继续执行)
注意的是:这两个方法是成对出现,通常使用在Enter,Exit之间。也可以用lock代替
代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var td = new ThredDemo(); Thread trOne = new Thread(new ParameterizedThreadStart(td.TrOne)); Thread trTwo = new Thread(new ParameterizedThreadStart(td.TrTwo)); //trOne启动线程 trOne.Name = "trOne"; trOne.Start(trOne.Name); //线程睡眠(相当于不参与cpu时间调度,通俗就是卡1000毫秒数) Thread.Sleep(1000); //trTwo启动线程 trTwo.Name = "trTwo"; trTwo.Start(trTwo.Name); Console.Read(); } } class ThredDemo { public List<int> obj; int i = 0; public ThredDemo() { obj = new List<int>(); } public void TrOne(object thredName) { //相当于lock 参考TrTwo Monitor.Enter(obj); Console.WriteLine("1"); // TrOne释放对象上的锁并阻止当前线程这个时候TrTwo启动并进入临界区 Monitor.Wait(obj); Console.WriteLine("2"); Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(),i); i++; Monitor.Pulse(obj); Console.WriteLine("3"); //TrOne进入等待 Monitor.Wait(obj); Monitor.Exit(obj); Console.WriteLine("4"); } public void TrTwo(object thredName) { lock (obj) { //TrTwo通过Wait 释放进入 这个时候TrOne阻塞i的值++ Console.WriteLine("5"); i++; //释放等待的(Wait)的线程 并马上自己阻塞等待TrOne Pulse Monitor.Pulse(obj); Console.WriteLine("6"); Monitor.Wait(obj); Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(), i); //释放 这样console输出的4一定在7的后面 因为TrOne阻塞需要TrTwo释放 当前前提是程序无BUG Monitor.Pulse(obj); -----标记 Console.WriteLine("7"); } } } }
为了方便理解自己加入输入查看效果 .
结果:
如果我把 TrTwo方法改下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var td = new ThredDemo(); Thread trOne = new Thread(new ParameterizedThreadStart(td.TrOne)); Thread trTwo = new Thread(new ParameterizedThreadStart(td.TrTwo)); //trOne启动线程 trOne.Name = "trOne"; trOne.Start(trOne.Name); //线程睡眠(相当于不参与cpu时间调度,通俗就是卡1000毫秒数) Thread.Sleep(1000); //trTwo启动线程 trTwo.Name = "trTwo"; trTwo.Start(trTwo.Name); Console.Read(); } } class ThredDemo { public List<int> obj; int i = 0; public ThredDemo() { obj = new List<int>(); } public void TrOne(object thredName) { //相当于lock 参考TrTwo Monitor.Enter(obj); Console.WriteLine("1"); // TrOne释放对象上的锁并阻止当前线程这个时候TrTwo启动并进入临界区 Monitor.Wait(obj); Console.WriteLine("2"); Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(),i); i++; Monitor.Pulse(obj); Console.WriteLine("3"); //TrOne进入等待 1分钟后 注意的是 // 如果指定的超时间隔已过,则线程进入就绪队列。 Monitor.Wait(obj,60000); Monitor.Exit(obj); Console.WriteLine("4"); } public void TrTwo(object thredName) { lock (obj) { //TrTwo通过Wait 释放进入 这个时候TrOne阻塞i的值++ Console.WriteLine("5"); i++; //释放等待的(Wait)的线程 并马上自己阻塞等待TrOne Pulse Monitor.Pulse(obj); Console.WriteLine("6"); Monitor.Wait(obj); Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(), i); //释放 这样console输出的4一定在7的后面 因为TrOne阻塞需要TrTwo释放 当前前提是程序无BUG // Monitor.Pulse(obj); Console.WriteLine("7"); } Console.WriteLine("8"); } } }
把Monitor.Pulse(obj);注释掉了 TrOne方法 Monitor.Wait(obj,60000);
运行后 4要等一分钟才输出 原因是 TrTwo方法没有释放 。
个人学习查看过程是 打印输出顺序查看执行过程 这样方便自己理解。
附加线程学习资料(来自博客园 )
逆时针の风 http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html
还有一线码农相对 逆时针の风 通俗懂一点
http://www.cnblogs.com/huangxincheng/category/362940.html
http://www.cnblogs.com/maitian-lf/p/3678128.html
http://www.cnblogs.com/maitian-lf/p/3672390.html