Monitor的另一种用法
在多线程编程时我们可以使用lock(obj){}代码块来控制关键代码的访问,lock其实是Monitor.Enter(obj)和Monitor.Exit(obj)的一种简单写法(语法糖)。
这个随笔的标题是“Monitor的另一种用法”,所以我们不赘述lock了;我们进入主题,另一种用法可以在一个线程获得对象锁后再释放锁,然后阻塞当前线程执行,直到收到Monitor发出的信号后再继续执行。
这里有两件事一个是获得锁然后释放锁并阻塞当前线程,做这件事儿要用Monitor的Wait()方法
另一件事是线程获得锁,然后执行一段操作并发出信号让第一件事儿中被阻塞的线程继续执行,这需要使用Monitor的Pulse或者PulseAll方法。
请看下面的代码片段:
class BlockingStack<T> { private readonly Stack<T> stack; public BlockingStack(Stack<T> theStack) { this.stack = theStack; } public void Push(T item) { lock (stack) { stack.Push(item); if (stack.Count == 1) { //这儿发出信号,唤醒在Pop中阻塞的线程 Monitor.PulseAll(stack); } } } public T Pop() { lock (stack) { if (stack.Count == 0) { //栈是空的,所以等待直到收到信号为止 Monitor.Wait(stack); } T item = stack.Pop(); return item; } } }
总结: Monitor类还可以锁定对象后释放锁等待另外一个线程发出信号后继续执行。
参考:
http://www.codeproject.com/KB/IP/socketasynceventargssampl.aspx
http://msdn.microsoft.com/en-us/library/system.threading.monitor.wait.aspx
http://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse.aspx