... continued
Continues the discussion on the Monitor class.
Ping Pong Example
We can rewrite our ping-pong example without busy waiting using Monitor
. The two threads Wait()
and Pulse()
to not busy wait. The code is self-explanatory and appears below, the widget runs for ten seconds and then timees out.
using System;using System.Threading;class Demonstration{private readonly object padlock = new object();private bool flag = false;void ping(){while (true){Monitor.Enter(padlock);while (flag){Monitor.Wait(padlock);}Console.WriteLine("Ping");flag = true;Monitor.Pulse(padlock);Monitor.Exit(padlock);}}void pong(){while (true){Monitor.Enter(padlock);while (!flag){Monitor.Wait(padlock);}Console.WriteLine("Pong");flag = false;Monitor.Pulse(padlock);Monitor.Exit(padlock);}}public void runTest() {Thread pingThread = new Thread(() =>{ping();});Thread pongThread = new Thread(() =>{pong();});pongThread.Start();pingThread.Start();pongThread.Join();pingThread.Join();}static void Main(){new Demonstration().runTest();}}
Using Value Types
One of the most common mistakes when using the Monitor
class is to pass value types as the object to synchronize on. Consider the snippet below:
int valueType = 5;Monitor.Enter(valueType);// Singal the monitorMonitor.Pulse(valueType);Monitor.Exit(valueType);
If we run the example above we get an object not synchronized exception. When we pass a value type to Monitor
's static methods, it is automatically boxed to a reference type. The conversion is implicit and each of three methods in the above example receive different objects as arguments that box the value type! This is the reason the code widget below throws up an ...