...

/

... continued

... 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.

Press + to interact
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:

Press + to interact
int valueType = 5;
Monitor.Enter(valueType);
// Singal the monitor
Monitor.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 ...

Access this course and 1400+ top-rated courses and projects.