2

I am trying to set the difference between synchronized and unsynchronized methods.. I have tried following code

 class Counter {
    private int counter = 10;
    public int getCounter() {
        return counter;
    }

    public synchronized void doIncrementAndDecrement() {
        counter++;
        keepBusy(500);
        counter--;
    }

    public void keepBusy(int howLong) { // (D)
        long curr = System.currentTimeMillis();
        while (System.currentTimeMillis() < curr + howLong)
            ;
    }
}

class MyCounterThread extends Thread {

    Counter c;

    public MyCounterThread(Counter c, String name) {
        // TODO Auto-generated constructor stub
        super(name);
        this.c = c;
        start();
    }

    @Override
    public void run() {
        for (;;) {
            c.doIncrementAndDecrement();
            sleepForSometime();
            System.out.println(c.getCounter());
        }
    }

    public void sleepForSometime() { // (D)
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class UnSynchronizedExapmle {

    public static void main(String[] args) throws InterruptedException {
        Counter c = new Counter();
        MyCounterThread t1 = new MyCounterThread(c, "A");
        MyCounterThread t2 = new MyCounterThread(c, "B");
        MyCounterThread t3 = new MyCounterThread(c, "C");
    }
}

So above i have doIncrementAndDecrement() synchronized method..

So i expected the value of counter should be 10 every time. But this wont happen i have the output is like

10
10
11
10
10
10
10
11
10
10
11
10
11
11
10
10
11
10
11
10
10
10
11
10
10
11
10

So please help me why this happens.. Or any blog/article for explaining difference between synchronized and asynchronized methods

Cœur
  • 37,241
  • 25
  • 195
  • 267
NullPointerException
  • 3,978
  • 4
  • 34
  • 52
  • A synchronous method is one which is run in the current thread. Java only supports synchronous methods. An asynchronous method is one which is executed in another thread or process i.e. asynchronously. Java doesn't support this directly but you can similate this with a library. – Peter Lawrey May 17 '12 at 07:28

3 Answers3

5

Your getCounter() method is not synchronized. So even though one thread might be locking the method, another thread can still access and print your counter variable

bobby
  • 2,629
  • 5
  • 30
  • 56
  • Yes it worked magically... I have one more doubt.. what difference it make if i write Thread.sleep() in my keepBusy() method.. because the output is quite different in both case – NullPointerException May 17 '12 at 07:39
  • 1
    The keepBusy() method you have written in the question is busy loop , meaning that while it executes, it is unlikely that any other thread gets a chance to run. This is not a recommended practice. You should use Thread.sleep() to give other Threads a chance to run. Have a look at http://stackoverflow.com/questions/4911397/what-is-a-busy-loop and http://stackoverflow.com/questions/4479443/thread-sleep-with-synchronization-in-java – bobby May 17 '12 at 08:22
  • Though if you really want to keep busy, the loop you have written is fine – bobby May 17 '12 at 08:25
2

You codes do not synchronized the getCounter method so that System.out.println may output the innerstate of counter. synchronized on method is as same as synchronized(this).

zsxwing
  • 20,270
  • 4
  • 37
  • 59
  • Yes it worked magically... I have one more doubt.. what difference it make if i write Thread.sleep() in my keepBusy() method.. because the output is quite different in both case – NullPointerException May 17 '12 at 07:42
  • 1
    keepBusy help you find the state of counter==11 easily. If you do not use keeyBusy, "counter++" and "counter--" usually run together(It's so fast that this thread usually will not be interrupted) so that you are hard to find the state of counter==11. – zsxwing May 17 '12 at 07:55
1

... what difference it make if i write Thread.sleep() in my keepBusy() method.. because the output is quite different in both case.

What it does is to make keepBusy() take a long time, and hence it makes getCounter() wait for a long time.

The difference in the output is due to the synchronization which prevents getCounter() from ever "seeing" the counter in the incremented state.

I mean what do the difference make Thread.sleep() and the above while loop in keepBusy() method make in terms of thread scheduling or locking..

It makes no difference.


For the record, it would bad idea for a real program to have a method like keepBusy() that sleeps in a synchronized method or block. The sleep causes any other thread that is trying to synchronize on the target object to be blocked ... and that's liable to reduce your application's actual parallelism.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216