Monitor: Mutual Exclusion in Single System

01 Apr 2011 by

Monitor

Monitor

Monitor and Semaphore is somehow the same. However, monitor adds more abstract layer to semaphore. Semaphore refers to operation level while monitor refers to class level which is the combination of many operations and variables.

Monitor

By definition, a monitor is a collection of procedures and data that are all grouped together in a class. Just as semaphore, monitor ensures that a particular thread can exclusively access to a shared resource at a specific time. Monitor may implement semaphore and condition variable over the critical section to provide the best total single flow of modifying the resources.

Requisite

This example of code below extending from the previous posts namely Principle of Mutual Exclusion and Semaphore: Mutual Exclusion in Single System. Please be sure you read those articles first.

Example

The example here is about to develop a Java monitor that take advantage of semaphore and conditional variable to give a single flow of modifying x and y. Be remember that, the example we want foo() runs before bar().

The structure of code is:

  • SharedVariable.java – a monitor class to prevent 2 threads from accessing shared resource concurrently
  • FooThread.java – thread engaging a shared resource
  • BarThread.java – thread engaging a shared resource
  • TestFooBar.java – main program to test a monitor class

Result

The final result of x and y is definitely fixed, x=10 and y=8 for every run. It means that our monitor is working properly in the way that we defined foo() runs before bar().

Source Code

SharedVariable.java

/**
 * A monitor class
 * @author http://lycog.com
 */
public class SharedVariable {
  //Global variables shared by many threads
  private int x=6;
  private int y=0;
  boolean fooDone = false;

  public void foo(){
    //semaphore
    synchronized(this){
      x++;
      y=x;
      fooDone = true;
      notify(); //signal the waited thread
    }
  }

  public void bar(){
    //semaphore
    synchronized(this){
      //condition variable
      if(!fooDone){
        try{
          wait();
        }catch(InterruptedException ie){ie.printStackTrace();}
      }
      y++;
      x+=3;
    }
  }

  public int getX(){
    return x;
  }

  public int getY(){
    return y;
  }
}

FooThread.java

/**
 * FooThread
 * @author http://lycog.com
 */
public class FooThread extends Thread{
  //Share variable
  private SharedVariable sv=null;

  public FooThread(SharedVariable sv1){
    this.sv = sv1;
  }

  @Override
  public void run(){
    //foo thread
    sv.foo();
  }
}

BarThread.java

/**
 * BarThread
 * @author http://lycog.com
 */
public class BarThread extends Thread{
  //Share variable
  private SharedVariable sv;

  public BarThread(SharedVariable sv1){
    sv = sv1;
  }

  @Override
  public void run(){
    //bar thread
    sv.bar();
  }
}

TestFooBar.java

/**
 * Test a monitor
 * @author http://lycog.com
 */
public class TestFooBar {
  public static void main(String[] args){
    //Loop 100 time to see the behavior
    for(int i=0; i<100;i++){
      //Share variable
      SharedVariable sv = new SharedVariable();

      //Two threads access shared resource
      FooThread foo = new FooThread(sv);
      BarThread bar = new BarThread(sv);

      //Start thread
      foo.start();
      bar.start();

      //wait for threads to finish
      try {
        foo.join();
        bar.join();
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }

      //Display the value of x and y
      System.out.println("X=" + sv.getX() + "  Y=" + sv.getY());
    }
  }
}

 

One response so far

Leave a Reply