oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Multithreading with C#
Pages: 1, 2, 3, 4

Inter-Thread Synchronization

Conceptually, threads are pretty simple to understand. Practically however, because they can inter-operate on the same data structures, they are a cause for programmatic headaches. Take the ThreadingExample class described at the beginning of this article -- there are many different permutations of results that may appear on the console when the program is run. Anything from

 1 2 3 4 5 1 2 3 4 5


 1 1 2 2 3 3 4 4 5 5


 1 2 1 2 3 3 4 5 4 5

is possible. (In reality, both programs had to be modified to count from 1 to 50 for me to demonstrate this to myself on my laptop.) The output is left to nuances of the operating system's thread scheduler. Sometimes it is necessary to make sure that only one thread can access a given set of data structures so as to make sure the data structures stay consistent -- and that is why we need inter-thread synchronization semantics.

In order to guarantee a certain behavior we have to coordinate the actions of the two threads through the use of locks. Both languages allow you to acquire a lock on any reference object -- once that lock is acquired, the program block can be assured that it is the only block that has acquired it. Also by using that lock, a program can wait until a signal comes through the variable causing the thread to wake up.

Table 2: Thread synchronization
The keywords to know when wanting to synchronize actions between threads in the two languages

Java C# Notes
synchronized lock

The C# lock statement is actually syntactic sugar for using the System.Threading.Monitor class's Enter and Exit methods

Object.wait() Monitor.Wait( object obj )

There is no wait method inherent to an Object. To wait for a signal, the System.Threading.Monitor class needs to be used instead. Both of these methods need to be executed in synchronized blocks

Object.notify() Monitor.Pulse( object obj )

See the notes for Monitor.Wait above

Object.notify() Monitor.PulseAll( object obj )

See the notes for Monitor.Wait above

We can modify the given example to let the variables increase in lock step in Java by first adding a variable to synchronize on and then modifying the count() method to

   public static Object synchronizeVariable = "locking variable";

   public static void count() {
     synchronized( synchronizeVariable ) {
       for( int count=1;count<=5;count++ ) {
         System.out.print( count + " " );  
         if( count < 5 )
           try {
           } catch( InterruptedException error ) {





What happens with these changes is that one thread, and one thread only (because only one thread can grab synchronizeVariable at at time), enters the for loop printing out 1. Next, it notifies all threads that are waiting on synchronizeVariable (although currently no threads are waiting) to wake up and attempt to grab the locking variable, and then it waits on the lock variable, which releases its hold on synchronizeVariable. The next thread can then enter the loop, print out 1, call notifyAll() to wake up the former thread and cause it to start attempting to grab hold of synchronizeVariable, then put itself into a wait(), releasing the variable to allow the former thread to grab it. This goes on until they have both printed 1 through 5 in lock step.

This can be easily translated into C# with a few syntactical changes

  public static Object synchronizeVariable = "locking variable";

  public static void Count() {
   lock( synchronizeVariable ) {
     for( int count=1;count<=5;count++ ) {
      Console.WriteLine( count + " " );nbsp; 
      Monitor.PulseAll( synchronizeVariable );
      if( count < 5 )
       Monitor.Wait( synchronizeVariable );




Some C# Goodies

As we have come to expect from C#, the language has a few more built-in methods, classes, and functionalities that Java does not have. These may prove to be helpful to the hardcore Java threads programmer, as they are usually items that Java programmers either wish for, write, or import into their own code.

Pages: 1, 2, 3, 4

Next Pagearrow