/*
 * Example from Script 2.?.
 *
 * int x = 0, y = 0, z;
 * con
 *   atomic z = x + y; end;
 *   atomic x = x + 1;
 *          y = y + 2; end;
 * end
 * println "x=", x, ", y=", y, ", z=", z;
 */
/* output:
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 3
   sync: x = 1, y = 2, z = 0   non sync: x = 1, y = 2, z = 0
   sync: x = 1, y = 2, z = 3   non sync: x = 1, y = 2, z = 1
*/
public class ex2 {

  public static int x, y, z;

  public static Object atom = new Object();

  public static int p = 100; 
 
  public static void main(String[] args) throws InterruptedException {

    if (args.length == 1) { 
       try { p = Integer.parseInt(args[0]); } 
       catch (NumberFormatException e) { } 
    } 

    for (int i=0; i<50; i++) {

      x = 0; y = 0; z = 0;

      Thread t1 = new Thread(new ex2act1());
      Thread t2 = new Thread(new ex2act2());

      t1.start();
      t2.start();

      t1.join();
      t2.join();

      System.out.print("sync: x = " + x + ", y = " + y + ", z = " + z);

      x = 0; y = 0; z = 0;

      Thread t3 = new Thread(new ex2act3());
      Thread t4 = new Thread(new ex2act4());

      t3.start();
      t4.start();

      t3.join();
      t4.join();

      System.out.println("   non sync: x = " + x + ", y = " + y + ", z = " + z);

    }
  }
 
  public static void probe() { 
    Sleep.sleep(p);
  }

}

class ex2act1 implements Runnable {
  public void run() {
    ex2.probe();
    synchronized (ex2.atom) { 
                  ex2.z = ex2.x + ex2.y; 
    }
  }
}

class ex2act2 implements Runnable {
  public void run() {
    ex2.probe(); 
    synchronized (ex2.atom) {
                  ex2.x = ex2.x + 1;
                  ex2.probe();
                  ex2.y = ex2.y + 2; 
    }
  }
}

class ex2act3 implements Runnable {
  public void run() {
    ex2.probe();
                  ex2.z = ex2.x + ex2.y; 
  }
}

class ex2act4 implements Runnable {
  public void run() {
    ex2.probe(); 
                  ex2.x = ex2.x + 1;
                  ex2.probe();
                  ex2.y = ex2.y + 2; 
  }
}

