A Steam Boiler
Home ] Up ] [ A Steam Boiler ] Race Conditions ] Monitors ] Synchronization ] A Fixed Steam Boiler ] Deadlock ] Starvation & Livelock ]

 

 

The following program is a simple emulation of a steam boiler. The boiler has a number of burners (this is a big boiler!), each one of which is programmed to burn fuel to keep the steam pressure up, unless the pressure exceeds a certain safety limit.

Class SteamBoiler represents the boiler, and class Burner represents a single burner. Each burner runs as a separate thread, and calls its burn() method to "burn fuel". The burn() method has a check to make sure that the pressure does not go beyond the safety limit.

You'll note that each burner just kicks in once, and then stops -- i.e. its thread dies. This is not realistic, but is done to keep things relatively simple. When all the threads have died, the main program prints out the resulting pressure, and exits.

Here's the code:

package unsynchronized;

/**
 *  NOTE: This implementation of the SteamBoiler class is implemented
 *  without regard to synchronization.  Because of this, it fails
 *  to maintain boiler pressure below the safety limit.
 */
public class SteamBoiler
{
  public static final int PRESSURE_LIMIT = 20;
  public static final int BURNER_COUNT = 10;
  
  public Burner[] start()
  {
    Burner[] burners = new Burner[BURNER_COUNT];
    for (int burner = 0; burner < BURNER_COUNT; burner++)
    {
      burners[burner] = new Burner(this);
      burners[burner].start();
    }
    
    return burners;
  }
  
  public int getPressure()
  {
    return m_pressure;
  }
  
  public void setPressure(int pressure)
  {
    m_pressure = pressure;
  }
  
  public static void main(String[] args)
  {
    SteamBoiler boiler = new SteamBoiler();
    
    Burner[] burners = boiler.start();
    
    for (int burner = 0; burner < BURNER_COUNT; burner++)
    {
      try
      {
        burners[burner].join();     // Wait for thread to finish
      }
      catch (InterruptedException e)
      {
        // This thread was interrupted.
      }
    }
    
    System.out.println("Pressure reads " + boiler.getPressure() +
        ", limit is " + PRESSURE_LIMIT);
  }
  
  /////// Data //////
  private int m_pressure = 0;
}

class Burner extends Thread
{
  public static final int PRESSURE_INCREMENT = 15;
  
  public Burner(SteamBoiler boiler)
  {
    m_boiler = boiler;
  }
  
  public void run()
  {
    burn();
  }
  
  private void burn()
  {
    if (m_boiler.getPressure() <
        SteamBoiler.PRESSURE_LIMIT - PRESSURE_INCREMENT)
    {
      // Wait to simulate delay
      try
      {
        sleep(100);
      }
      catch (InterruptedException e)
      {
        // Ignore
      }
      
      m_boiler.setPressure( m_boiler.getPressure() +
          PRESSURE_INCREMENT );
    }
  }
  
  ///// Private data //////
  private SteamBoiler m_boiler;
}

However, when the program is run, you'll find that it outputs the following:

Pressure reads 150, limit is 20

Here's an applet that uses the above class and displays the boiler pressure in a more graphical form:

Whoops! Your browser doesn't seem to be capable of running Java applets! Please enable Java applets.

Here's the source for this applet.

(Perhaps I should add some explosive effects?) 

So what's going on?

 

The page was last updated February 19, 2008