Monitor的Wait和Pulse要领在线程的同步锁使用中是对照庞大的,理解稍微困难些,但也是内涵相当丰富和
微妙的!通过他们你可以本身实现AutoResetEvent,ManualResetEvent等同步东西,同时还会在效率和内存
使用上有个质的提高!
今天在MSDN查阅Monitor东西时,发明其下的成员要领的Demo都是用一个安适的同步Queue来论述的,但是
代码注解和自己MSDN的专业术语晦涩难懂,造成这个实例并不是好理解,这里我将注释都添加到了关键语句上,,
同时最后结合代码分析这个同步Queue是如安在Monitor的Wait和Pulse的指导下事情的:
此刻我对整个代码做一个流程分析:
在这个特定配景下,线程优先挨次: 【期待行列队伍】->【就绪行列队伍】->【拥有锁线程】这个是重点,下文多
次会提到,此中的微妙关系的核心也来源于这个执行挨次。
MSDN官方备注:同步的东西包罗若干引用,此中包孕对当前拥有锁的线程的引用、对就绪行列队伍的引
用和对期待行列队伍的引用。
我的提醒:竞争东西锁的线程都是处于就绪行列队伍中。
在本案例中我将FirstThread和SecondThread要领当作是A,B线程(这是完全可以的,因为A,B是两个线程的
回调函数都是同级的事情者线程),
下面是分析法式:
/*情形1:假设A线程获取了m_smplQueue同步东西锁:
* 1、开始循环,挪用Monitor.Wait(m_smplQueue):A线程释放本身对同步东西的锁,流放本身到
期待行列队伍(B线程一开始就竞争同步锁所以处于就绪行列队伍中),直到本身再次获得锁,否则一直梗阻。
所以A线程运行到这里就暂停了。
* 2、这时候B直接从就绪行列队伍出来获得了m_smplQueue东西锁,Monitor.Pulse(m_smplQueue):执
行时,会将A线程放行到就绪行列队伍,A筹备获取对锁的拥有权。
* 3、执行循环,Monitor.Wait(m_smplQueue, 1000):B线程将本身流放到期待行列队伍并释放自身对
同步锁的独有,该期待设置了1S的超时值,当B线程在1S之内没有再次获取到锁则自动添加到就绪
行列队伍,或者这期间收到Pulse的脉冲信号。
* 4、B线程由于1S之内都返回false,lock块迅速结束,也即退出对m_smplQueue独有权,A由就绪
行列队伍中进入对m_smplQueue的独有、继续.
* 5、在1中陈说的Monitor.Wait(m_smplQueue)的梗阻结束,返回true,执行接下来的代码:
m_smplQueue.Enqueue(counter)向行列队伍中插手元素,执行下一行的Monitor.Pulse(m_smplQueue),
由于第3条的1S没到(我相信地球上目前已没有这么慢的CPU了),B线程收到脉冲,将本身添加到就
绪行列队伍,counter计数+1,A线程的lock结束,A则进入期待行列队伍.
* 6、由于B从就绪行列队伍再次获得独有权,Monitor.Wait(m_smplQueue, 1000)返回true,while进入循
环内部,弹出第一条元素,打印出来。 挪用Monitor.Pulse(m_smplQueue)将A线程插手到就绪行列队伍,
同时while结束,lock块结束,B退出对东西锁的独有进入到期待行列队伍中.
* 7、A继续,遵循这个规律循环往复知道所有的数被打印出来...
*
* 情形2:B线程先获取了m_smplQueue同步东西锁:
* 1、进入lock块,Monitor.Pulse(m_smplQueue)执行:由于当前的A线程已经处于就绪行列队伍
所以收到也没感化(那么你必定再问那这句有什么用啊?没错是得问,你发明没如果是A线程开始是
否就有用了啊!这就是它的感化!).
* 2、开始while (Monitor.Wait(m_smplQueue, 1000))中的判断,技术细节还是遵循上面所讲的,B这时
候会自动将本身流放到期待行列队伍并在这里梗阻(也许1S到期了也会将它安排到就绪行列队伍中去,这个感化
主要是防备死锁,因为咱们的就绪行列队伍可不能为空啊,这在上面我忘了讲了这里增补下),于是乎A
获得了m_smplQueue独有权,于是乎又回到了上面从A先获得线程锁的流程....
*
* 总之,这个操纵目的是让多个线程操纵一个Queue时,连结同步:不能在无数据时出队,一旦有
一个数据就顿时可以出队,最终的效果是没有一个元素在行列队伍中。