多线程一直在学习和理解中......
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
多线程同步_Monitor,码迷,mamicode.com