Home : Course Map : Chapter 8 : Java :
Demo: Exclusive Thread Operations
JavaTech
Course Map
Chapter 8

Introduction
Threads Overview
  Demo 1   Demo 2
Stopping Threads
Multi-Processing
Thread Tasks
Animations
 
 Demo 3   Demo 4  
  Demo 5

Non-interacting
  Demo 6

Task Splitting
  Demo 7

Exclusivity
  Demo 8

Communicating
  Demo 9

Priority/Scheduling
More Thread

Exercises

    Supplements
Java2D Animation
  Demo 1 
Processor View
More Concurrency
Cloning
  Demo 2  Demo 3 

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

Threading becomes tricky when threads perform operations that can conflict with each other. For example, say that we face the following situation.

An object of class Filler wants to put a number into the Cavity attribute of an instance of class Box. It can only do this when the cavity is empty.

Class Getter wants to retrieve the number from Cavity and then leave the Cavity empty.

Ideally, Filler and Getter would alternate their calls to the methods put() and get().

However, if no special steps are taken, it is quite easy for Getter to call get() when the Cavity is empty and for Filler to call put() when the Cavity is still full.

This type of situation is called a data race because each thread is racing to do its task without waiting for the other thread to finish its activity.

A synchronization scheme is used to prevent this problem. The solution is to make the threads wait in single file at the method or code block where the conflict can occur.

In the case above, this means that an instance of Box only allows one thread at a time to invoke its put() or get().

It is as if only one thread object owns the key to the lock on the doors to Box. It must give up the key (though by tradition you say that the thread gives up the lock) before any other thread can access a synchronized method on the object.

Note that each instance has its own lock. There is no interference problem among different instances of Box. A lock on one instance has no affect on access to put() and get()on another instance of box.

Synchronized Methods

When a process invokes put() or get(), which have the synchronized modifier, for an instance of the Box class below, it will wait until it is granted the lock for that object. The process continues through the method. However, if a flag is not set it will invoke the wait() method. This allows the process to give up the lock and remain at that point in the computation until a notifyAll() method is called.

The notifyAll() will wake up all the currently waiting threads and check if they can have the lock for this particular object. If one process gets the lock then it proceeds though the method and then invokes notifyAll(), which will wake up any other waiting threads.

ExclusiveApplet.java
+ Box.java + Getter.java + Filler.java
+ Outputable.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
  * This demo applet illustrates synchronization with the
  * Filler thread trying to fill the bin in the Box object
  * and the Getter thread trying to get the value from the
  * bin. The Filler must wait if the bin already is full while
  * the getter must wait if it is empty.
  *
  * Output of the thread goes to the text area on the applet
  * interface. The applet implements the Outputable interface.
  *
  * Derived from Java Tutorial Cubbyhole/Producer example.
**/
public class ExclusiveApplet extends JApplet
             implements Outputable, ActionListener
{
  // A Swing textarea for display of string info
  JTextArea fTextArea = null;

  /**
    * Create a User Interface with a textarea with sroll bars
    * and a Go button to initiate processing and a Clear button
    * to clear the textarea.
   **/
  public void init  () {
    Container content_pane = getContentPane  ();
    JPanel panel = new JPanel  (new BorderLayout  ());

    // Create a text area.
    fTextArea = new JTextArea  ();

    // Make it editable
    fTextArea.setEditable  (false);

    // Add to a scroll pane so that a long list of
    // computations can be seen.
    JScrollPane area_scroll_pane = new JScrollPane  (fTextArea);

    panel.add  (area_scroll_pane,BorderLayout.CENTER);

    JButton go_button = new JButton  ("Go");
    go_button.addActionListener  (this);

    JButton clear_button = new JButton  ("Clear");
    clear_button.addActionListener  (this);

    JPanel control_panel = new JPanel  ();
    control_panel.add  (go_button);
    control_panel.add  (clear_button);

    panel.add  (control_panel,BorderLayout.SOUTH);

    // Add text area & control panel.
    content_pane.add  (panel);
  } // init

  /** Respond to the buttons to start the threads or to clear
    * the text area.
   **/
  public void actionPerformed  (ActionEvent e) {
    if  ( e.getActionCommand  ().equals  ("Go"))
        start  ();
    else
        fTextArea.setText  (null);
  } // actionPerformed

  /** Create Filler and Getter thread instances and
    * start them filling and getting from a Box instance.
   **/
  public void start () {
     Box b = new Box (this);
     Filler f1 = new Filler (b);
     Getter b1 = new Getter (b);

     f1.start ();
     b1.start ();
  } // start

  /** Overided Outputable println to send string to text area.**/
  public void println  (String str)  {
    fTextArea.append  (str + CR);
  }

  /** Overided Outputable print to send string to text area.**/
  public void print  (String str) {
    fTextArea.append  (str);
  }

}// class ExclusiveApplet

/**
  * Use synchronized methods to "put" and "fill"
  * a bin, which holds some number passed to it.
  * A flag indicates whether the bin is in a filled state
  * or not.

  * The put method goes into wait state if bin is filled.
  * Similarly, the get method waits if bin not filled.
  * When they emerge from the wait states, the processes
  * do their given tasks and then invoke notifyAll () to
  * wake up other threads that might be waiting on the
  * object.

  *
**/
public class Box {
  private int fBin;
  private boolean fFilled = false;
  Outputable fOut;

  /** Constructor obtains reference to Outputable object.**/
  Box (Outputable out){
    fOut = out;
  }

  /**
    * If bin is not filled, wait for it to be.
    * If bin filled, then empty it  (i.e. set flag to false.)
    * Notify other waiting threads that are in wait state
    * on this object. Return the value in the bin.
   **/
  public synchronized int get () {
    while  (fFilled == false){
      try {
         wait ();
      }
      catch  (InterruptedException e) { }
    }
    fFilled = false;
    fOut.println ("Get value: " + fBin);
    notifyAll ();
    return fBin;
  } // get

  /**
    * If bin is filled, wait for it to be emptied.
    * If bin not filled, then fill it  (i.e. set flag to true.)
    * Notify other waiting threads that are in wait state
    * on this object.
   **/
   public synchronized void put (int value){
    while  (fFilled == true) {
      try  {
         wait ();
      } catch  (InterruptedException e)  { }
    }
    fBin = value;
    fFilled = true;
    fOut.println ("Put value: " + fBin);
    notifyAll ();
  } // put
  
} // class Box

/** Retrieve the value from the Box object.**/
public class Getter extends Thread {
  private Box fBox;
  private int fNumber;

  public Getter (Box b) {
    fBox = b;
  } // ctor

  public void run () {
    for (int i = 0; i < 10; i++) {
         fNumber = fBox.get ();
    }
  } // run

} // class Getter

/**
  * A thread to fill the bin in the Box object.
  * Derived from Java Tutorial Cubbyhole/Producer example
**/
public class Filler extends Thread {
  private Box fBox;

  public Filler (Box b) {
    fBox = b;
  } // ctor

  public void run () {
    for  (int i=0; i<10; i++){
      fBox.put (i);
      try {
          sleep ( (int) (Math.random () * 100));
      }
      catch  (InterruptedException e) { }
    }
  } // run
  
} // class Filler

 

The output of this program shows that the filler and getter threads do not get into a data race.

References & Web Resources

Latest update: Nov. 6, 2004

              Tech
Timers
  Demo 1
Hist. Adapt Range
  Demo 2
Sorting in Java
  Demo 3
Histogram Median
  Demo 4
Refactoring
  Demo 5
Error Bars
  Demo 6
Exercises

           Physics
Least Squares Fit
  Demo 1
Fit to Polynomial
  Demo 2
Fit Hist Errors
  Demo 3
Discretization
  Demo 4
Timing
  Demo 5
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.