所谓锁,就是之锁定的区域只能单个线程进入进行操作,其他线程在锁的外围等待。
Monitor锁通过Monitor.Enter(obj)和Monitor.Exit(obj)来锁定和解锁。
Lock锁则直接Lock(obj)进行锁定。
Monitor锁和Lock锁很类似,实质Lock锁是Monitor的变体。
lock(obj)
{
}
等价为:
try
{
Monitor.Enter(obj)
}
catch()
{}
finally
{
Monitor.Exit(obj)
}
所以lock能做的,Monitor肯定能做,Monitor能做的,lock不一定能做。
下面讲一下Monitor的特殊与Lock功能。
Monitor.Enter(obj);// 启动锁 Monitor.TryEnter(obj, 1000);//启动锁,也是区别于Lock的功能,多了一个时间设置,就是等待多少时间后如果还不能进入,则取消此次操作。Lock则会一直等待下去。 Monitor.Wait(obj);// 会放弃当前线程对资源的所有权,让别的线程到lock进来。然后当别的线程代码里Pulse一下(让原线程进入到等待队列),之后从Waint()后面继续运行下去
Monitor.Pulse(obj);// 恢复原放弃资源控制权的线程,使其重新进入到等待队列中,下次直接从Wait()后继续运行。
Monitor.PulseAll(obj);// 恢复所有曾今放弃资源控制权的线程,使其重新进入到等待队列中
Monitor.Exit(obj);// 结束锁
例子:
[MethodImpl(MethodImplOptions.Synchronized)] private void FirstThread() { //Monitor.Enter(this); Monitor.Wait(this); MessageBox.Show("FirstThread"); //Monitor.Exit(this); } private void SecondThread() { Monitor.Enter(this); Monitor.Wait(this); MessageBox.Show("SecondThread"); Monitor.Pulse(this); Monitor.Exit(this); } private void ThirdThread() { Monitor.Enter(this); MessageBox.Show("ThirdThread"); Monitor.Pulse(this); Monitor.Exit(this); }
调用:
Thread thread = new Thread(new ThreadStart(FirstThread)); thread.Name = "thread1"; Thread thread2 = new Thread(new ThreadStart(SecondThread)); hread2.Name = "thread2"; Thread thread3 = new Thread(new ThreadStart(ThirdThread)); thread3.Name = "thread3"; thread.Start(); thread2.Start(); thread3.Start();
运行结果:
首先线程会进入到FirstThread方法,然后因为Wait了,所以线程1放弃所有权,然后线程2进入SecondThread,因为也Wait了,所以线程3进入ThirdThread,然后会MessageBox弹出“TirdThread”,之后运行Pulse,所以释放了线程2,所以线程2会MessageBox弹出“SecondThread”,之后再释放线程1弹出“FirstThread”。
每一个锁都必须要有Enter和Exit,里面参数是一个Object类型,是一个锁的标识。
在这FirstThread方法中没有使用Enter和Exit而是使用了
[MethodImpl(MethodImplOptions.Synchronized)]
这个作用相当于在这个方法开始和结尾处分别加上了Enter和Exit。