views:

51

answers:

4
/*
This should always produce 0 as output since all three methods increment(), decrement(), value()  are thread safe(synchronized).  but it is returning 1
*/

class Counter implements Runnable {
    private int c = 0;

    public  synchronized void increment() {
        c++;
    }
    public synchronized void decrement() {
        c--;
    }
    public synchronized int value() {
        return c;
    }
    public void run() {
        try {
            this.increment();
            Thread.sleep(1000);
            this.decrement();
            Thread.sleep(1000);
            this.increment();
            Thread.sleep(1000);
            this.decrement();
            Thread.sleep(1000);
        }
        catch (InterruptedException e){
            return;
        }
    }
    public static void main(String args[]) throws InterruptedException {
       Counter c =  new Counter();
       new Thread(c).start();
       new Thread(c).start();
       System.out.println(c.value());
    }

}
+1  A: 

You are reading the value before the threads have finished execution, so it may be well different from zero.

starblue
+1  A: 

You're not waiting for the threads to complete running, so the result is that the value of c is printed at whatever it is at that second. I bet if you tried it 1000 times, there would be times when it wasn't 1.

IBM has a fair tutorial on the situation you're encountering: http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzahw/rzahwex3rx.htm

San Jacinto
+4  A: 

There's nothing to control when the main thread is calling value(). It will run as soon as it can acquire a lock on c, even though the other threads are still running.

If you want to wait until the threads are done, call join() on them.

erickson
+6  A: 

like everyone else said you need to make sure that the treads have finished executing, to do that you need to call join. for example

public static void main(String args[]) throws InterruptedException {
   Counter c =  new Counter();
   Thread t1 = new Thread(c).start();
   Thread t2 = new Thread(c).start();
   t1.join();
   t2.join();
   System.out.println(c.value());
}

that should run correctly

luke