.Net’s Monitor pattern

C# brought us two interesting tools: the Monitor and the Threadpool. Neither of them was anything new, especially the threadpool.
The monitor is a powerful concept, a generalization of the semaphores, the versatility of which has been demonstrated years ago. The monitor allows to implement conditions that can be signaled, which allows threads to wait for a specific state and then do perform their tasks atomically!

The general approach is to associate a variable, or a consistent set of variables to a monitor instance, and then, use this pattern

...
lock(_monitor)
{
  while(!conditionIsMet)
  {
    Monitor.Wait(_monitor);
  }
  // here we know the conditions are met
  // and that we have exclusive access
  // so do some work
  ...
  // if we have changed the variables, we can skip it otherwise
  Monitor.PulseAll(_monitor);
}


Its strength lies in the Wait method which releases the lock and then waits for a notification atomically, which is error prone to implement manually. When one is used to work with Mutexes and Events, it takes some time to get accustomed to. But rewards are great because most synchronization patterns can be implemented safely, easily and with maintainable code.

Alas, .Net team missed an opportunity to have a great API which pushed developers in the pit of success.

    The design should push toward using PulseAll() instead of Pulse()!

They should also probably have secured the use of while(condition) Monitor.Wait();.

Why all those critics to an otherwise fine piece of API?
Well, using Pulse can lead to deadlocks! My first Can You Spot gave a good example of the risks, but it was obvious. Next one will be devious, but still relying on that weakness.
The problem with Pulse is that you must be sure that only one thread has to be waken up. If this assumption holds true, then you are golden. Otherwise, you are one deadlock away from misery.
The good news is that it is often true, but not always. But this decision shortcut also led to a slightly degenerated monitor pattern:

...
lock(_monitor)
{
  if(!conditionIsMet) // notice it was 'while' before. 
  {
    Monitor.Wait(_monitor);
  }
  // here we know the conditions are met
  //  and that we have exclusive access
  // so do some work
  ...
  // if we have changed the variables, we can skip it otherwise
  Monitor.Pulse(_monitor);
}

The difference may look subtle, but suddenly the assumption is now that the condition is true if some other thread signals the monitor, as it is no longer checked after the call to Wait. It may well not be the case, and then you start facing a really nasty bug. The rule is ‘check your condition in a while loop, not a simple if’.

Back to the original topic: PulseAll() vs Pulse(). You may be wondering why .Net provides two variants for that mechanism, especially after my comments regarding the dangers of Pulse(). Well, PulseAll() is probably more expensive than a simple Pulse(), but not by a wide margin either. Looking at Rotor source code, PulseAll() loops through all waiting threads to wake them up all instead of just the first one. As far as I know, there is nothing I consider an issue with PulseAll(), you have one annoyance: PulseAll does not ensure fairness among threads. But that is rarely an issue.

Take away: use the Monitor pattern, it is an excellent synchronization tool, but use it properly, or it will bite you. Well, what doesn’t, when you really think about it 🙂

As a conclusion, for me it is a missed opportunity for a ‘pit of success’ design. I would have proposed to have Pulse() wake all threads and offered a PulseOne method.

Multithreading and skillset

Is multithreading a complex subject that should be handled only by experts?

This is a fundamental question, that deserve proper care. If experts are mandatory, the problem is that they are hard to get by. Assuming you have enougth of those, we need to address the problem of code integration with non expert developers. Having the expert turning non multithreaded code to multithreaded one does not work; actually it can work at the algorithm level, but at the application level. And then, non experts can no longer modify the code.
The other way around would be having experts lay down some scaffolding code for the rest of the development force to fill in. It looks like a better approach because fix can be made by anyone, as long as it does not pertain to the scaffolding code.
Let’s go one step further and isolate scaffolding code from so called ‘business code’.
Et Voilà!, we have a nice framework. Which has been designed by experts from the ground up.
That is in essence my opinion: all developpers must be able to leverage multithreading. But like several others technical fields, such as databases, middlewares or 3D to name a few, we need to remove the burden from the mass of developpers.

The next question is then: how do we design such a framewok to be a pit of success.