/**************************************************************
*  Name       : SeparateDemo.java
*  Book Title : The Java(TM) Programming Language, Third Edition
*  ISBN       : 0-201-70433-1
*  Author     : Ken Arnold, James Gosling, David Holmes
*  Publisher  : Addison Wesley (www.awl.com)
*  Creator    : Liqwid Krystal, Inc. (www.liqwidkrystal.com)
*
*  Page(s)    : 239-240
*  Copyright  : 2000 by Sun Microsystems, Inc.
**************************************************************/

/*
  This program increases the concurrency level of a class 
  by using several locks.
*/

class SeparateGroups {
    private double aVal = 0.0;
    private double bVal = 1.1;

    protected Object lockA = new Object();
    protected Object lockB = new Object();

    public double getA() {
        synchronized (lockA) {
           System.out.println( Thread.currentThread().getName() + 
                        " holds lockA and gets aVal=" + aVal);  
            return aVal;
        }
    }

    public void setA(double val) {
        synchronized (lockA) {
           System.out.println( Thread.currentThread().getName() + 
                        " holds lockA and sets aVal to " + val);  
            aVal = val;
        }
    }

    public double getB() {
        synchronized (lockB) {
           System.out.println( Thread.currentThread().getName() + 
                        " holds lockB and gets bVal=" + bVal);  
            return bVal;
        }
    }

    public void setB(double val) {
        synchronized (lockB) {
           System.out.println( Thread.currentThread().getName() + 
                        " holds lockB and sets bVal to " + val);  
            bVal = val;
        }
    }

    public void reset() {
        synchronized (lockA) {
            synchronized (lockB) {
        System.out.println( Thread.currentThread().getName() + 
            " holds both lockA and lockB and resets to 0.0");  
                aVal = bVal = 0.0;
            }
        }
    }
}



/** class to define the threads for synchronized execution */

public  class SeparateDemo implements Runnable {
    private double a, b;
    private SeparateGroups s = new SeparateGroups();

    SeparateDemo(double a,double b) {
        s.reset();
        this.a = a;
        this.b = b;
    }
    
    public void run() {
        s.setA(a);
        System.out.println(Thread.currentThread() + 
                               ".aVal = " + s.getA());

        s.setB(b);
        System.out.println(Thread.currentThread() + 
                               ".bVal = " + s.getB());
    }
    
    public static void main(String[] args) {

        SeparateDemo dem1 = new SeparateDemo(5.0, 8.0);
        SeparateDemo dem2 = new SeparateDemo(9.0, 12.0);

        new Thread(dem1,"dem1").start();
        new Thread(dem2,"dem2").start();
    }
}





/*
// The sample output from this program: note that the order of
// execution changes unpredictably

// 1st run

Thread[dem2,5,main].aVal = 9.0
Thread[dem1,5,main].aVal = 5.0
Thread[dem2,5,main].bVal = 12.0
Thread[dem1,5,main].bVal = 8.0

// 2nd run

Thread[dem1,5,main].aVal = 5.0
Thread[dem2,5,main].aVal = 9.0
Thread[dem1,5,main].bVal = 8.0
Thread[dem2,5,main].bVal = 12.0

*/