import java.util.concurrent.locks.*;

public class Locked{
    public static void main (String[] args) throws Exception {
        new Locked().main();
    }
    
    private void main() throws Exception {
        Thread[] T = new Thread[10];
        
        for (int k=0; k < T.length; k++) {
            T[k] = new MyThread();
        }
            
        for (int k=0; k < T.length; k++) {
            T[k].start();
        }
            
        for (int k=0; k < T.length; k++) {
            T[k].join();
        }
            
        System.out.println("Ctr = "+Ctr.value());
        System.out.println("<enter> to exit");
        System.in.read();
    }
    
    Counter Ctr = new Counter();
    
    private /*final*/ ReentrantLock lck = new ReentrantLock();

    class MyThread extends Thread {
        public void run() {
            try {
                for (int i=0; i<100; i++) {
                    Ctr.increment();
                    Ctr.decrement();
               }
            } catch (Exception ex) {}
        }
    }
    
    class Counter {
        private int c = 0;

        public void increment() throws Exception {
            lck.lock();
            try {
                int r = c;
                r += 1;
                Thread.yield();  
                //Thread.sleep((int) (2*Math.random()));
                c = r;
            } finally {
                lck.unlock();
            }
        }

        public synchronized void decrement() throws Exception {
            lck.lock();
            try {
                int r = c;
                r -= 1;
                Thread.yield();  
                //Thread.sleep((int) (2*Math.random()));
                 c = r;
            } finally {
                lck.unlock();
            }
        }

        public synchronized int value() {
            lck.lock();
            try {
                return c;
            } finally {
                lck.unlock();
            }
        }
    }
}
