Universidad de Costa Rica

Escuela de Ciencias de la Computación e Informática

CI-0122 Sistemas Operativos

Temas

CI0122 / Temas revisados / Semana-06 / Java / H2O


/**
 *   Java solutions to H2O synchronization problem
 *
 *   Main thread will generate H or O atoms which you need to synchronize to make water
 *
 *   Reminder: Java parameter passing are by value
 *
 *   We create a shared resources class to allow each thread access them
 *
 **/
 
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;

//A shared resource/class
class Shared {
    private Lock lock;
    private AtomicInteger cH;
    private AtomicInteger cO;
    private Semaphore SemH;
    private Semaphore SemO;

    public Shared() {
       lock = new ReentrantLock();
       cH = new AtomicInteger();	// Inits variable to zero
       cO = new AtomicInteger();
       SemH = new Semaphore( 0 );       // Semaphore variable initialized to 0
       SemO = new Semaphore( 0 );
    }

    public void getLock() {
       lock.lock();
    }

    public void releaseLock() {
       lock.unlock();
    }

    public int getH() {
       return cH.get();
    }

    public int getO() {
       return cO.get();
    }

    public void IncH() {
       cH.getAndIncrement();
    }

    public void DecH() {
       cH.getAndDecrement();
    }

    public void IncO() {
       cO.getAndIncrement();
    }

    public void DecO() {
       cO.getAndDecrement();
    }

    public void SignalH() {
       this.SemH.release();
    }

    public void SignalO() {
       this.SemO.release();
    }

    public void WaitH() {
       try {
          this.SemH.acquire();
       } catch ( InterruptedException e ) {
       }
    }

    public void WaitO() {
       try {
          this.SemO.acquire();
       } catch ( InterruptedException e ) {
       }
    }

}
  
class Particle extends Thread {
    Random r;
    int number;
    Shared resources;		// Create all shared variables, only one instance

    public Particle( int i, Shared res ) {
       this.number = i;
       this.r = new Random();
       this.resources = res;
    } 
  
    @Override
    public void run() {
       if ( 0 == (r.nextInt() & 3) ) {	// Create a new particle, randomly select hydrogen and oxygen
          this.O( this.number );
       } else {
          this.H( this.number);
       }

    }


/**
 *   Oxygen atom method
 *
 *   Check for two hydrogen atoms to make water, else wait
 *
 **/
    public void O( int id ) {
       resources.getLock();		// Get exclusive acess
       System.out.println("Starting O thread " + this.number + " ... cO(" + resources.getO() + "), cH(" + resources.getH() + ")" );
       if ( resources.getH() > 1 ) {
          System.out.println("\t O particle thread " + id + " is making water :) ... cO(" + resources.getO() + "), cH(" + resources.getH() + ")" );
          resources.DecH(); resources.DecH();	// Report use of two hydrogen atoms
          resources.releaseLock();				// Release lock
          resources.SignalH();				// Signal to required hydrogen atoms
          resources.SignalH();
       } else {
          resources.IncO();					// Report one more oxygen atom
          resources.releaseLock();				// Release lock and wait
          resources.WaitO();
       }
    }


/**
 *
 *   Hydrogen atom method
 *
 *   Check for another hydrogen and one oxygen to make water, else wait
 **/
    public void H( int id ) {
       resources.getLock();
       System.out.println("Starting H thread " + this.number + " ... cO(" + resources.getO() + "), cH(" + resources.getH() + ")" );
       if ( (resources.getH() > 0) && (resources.getO() > 0) ) {
          System.out.println("\t H particle thread " + id + " is making water :) ... cO(" + resources.getO() + "), cH(" + resources.getH() + ")" );
          resources.DecH();
          resources.DecO();
          resources.releaseLock();
          resources.SignalH();
          resources.SignalO();
       } else {
          resources.IncH();
          resources.releaseLock();
          resources.WaitH();
       }
    }

} 
  
// Driver class 
public class Agua {
    public static void main(String args[]) throws InterruptedException {
        Shared agua = new Shared();

        Thread particles[] = new Thread[ 100 ];

        for ( int i = 0; i < 100; i++ ) {
           particles[ i ]  = new Particle( i, agua );
           particles[ i ].start();
        }

        // waiting for threads
        for ( int i = 0; i < 100; i++ ) {
           try {
              particles[ i ].join();
           } catch ( InterruptedException e) {
           }
 
        }
    }

}