所谓锁,就是之锁定的区域只能单个线程进入进行操作,其他线程在锁的外围等待。 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。