Anup Verma
Anup Verma

Reputation: 183

Why does synchronization not work in the second code?

Synchronization works correctly in this code:

    class PrintNumbers {
        synchronized public void display() {
            System.out.println("in display");
            for (int i = 0; i < 3; i++) {
                System.out.println("Thread name : "+ Thread.currentThread().getName() + " i= " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.getMessage();
                }
            }
            System.out.println("out of display");
        }
    }

    class MyThread implements Runnable {
        Thread t;
        PrintNumbers printNumbers;

        MyThread(PrintNumbers printNumbers, String s) {
            this.printNumbers = printNumbers;
            t = new Thread(this,s);
            t.start();
        }

        public void run() {
            printNumbers.display();
        }
    }

    class SyncExample {
        public static void main(String[] args) {
            PrintNumbers printNumbers = new PrintNumbers();

            new MyThread(printNumbers, "My Thread 1");
            new MyThread(printNumbers, "My Thread 2");
        }
    }

Output:

in display  
Thread name : My Thread 1 i= 0  
Thread name : My Thread 1 i= 1  
Thread name : My Thread 1 i= 2  
out of display
in display  
Thread name : My Thread 2 i= 0  
Thread name : My Thread 2 i= 1  
Thread name : My Thread 2 i= 2  
out of display

but not in this code:

    class PrintNumbers {
        synchronized public void display() {
            System.out.println("in display");
            for (int i = 0; i < 3; i++) {
                System.out.println("Thread name : "+ Thread.currentThread().getName() + " i= " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.getMessage();
                }
            }
            System.out.println("out of display");
        }
    }

    class MyThread implements Runnable {
        Thread t;
        PrintNumbers printNumbers;

        MyThread(String s) {
            this.printNumbers = new PrintNumbers();
            t = new Thread(this,s);
            t.start();
        }

        public void run() {
            printNumbers.display();
        }
    }

    class SyncExample {
        public static void main(String[] args) {
            new MyThread("My Thread 1");
            new MyThread("My Thread 2");
        }
    }

Output:

in display  
Thread name : My Thread 1 i= 0  
in display  
Thread name : My Thread 2 i= 0  
Thread name : My Thread 1 i= 1  
Thread name : My Thread 2 i= 1  
Thread name : My Thread 2 i= 2  
Thread name : My Thread 1 i= 2  
out of display  
out of display  

I cannot understand what difference wrt Synchronization does it make to initialize PrintNumbers in the Runnable MyThread and in the SyncExample class. Please explain.

Upvotes: 5

Views: 83

Answers (3)

T.J. Crowder
T.J. Crowder

Reputation: 1074008

I cannot understand what difference wrt Synchronization does it make to initialize PrintNumbers in the Runnable MyThread and in the SyncExample class.

It doesn't. What does matter is that in your first example, you have only one PrintNumbers instance which both threads share. But in your second example, you have two separate PrintNumbers instances, one for each thread.

Since PrintNumbers#display synchronizes on the instance (synchronized instance methods synchronize on this), it only synchronizes within the instance, not across multiple instances.

When both threads share an instance, the two calls to display are serialized. But when the threads each have their own instance, the two calls to display are on separate instances, and thus there is no serialization of the calls, they can overlap.

Upvotes: 5

Sami Kuhmonen
Sami Kuhmonen

Reputation: 31143

It is working in both cases as it should. The difference is that in the first case you have a single object that is synchronized. In to second one you have two. They both are called only once so they are synchronized perfectly.

synchronized doesn't work between objects, only within one.

Upvotes: 3

Filipp Voronov
Filipp Voronov

Reputation: 4197

Because in the second code each thread has its own PrintNumbers object so they work in parallel. In the first one they share the single PrintNumbers object and work with it in synchronized way.

PS. Remember that synchronized for non-static methods makes synchronization on object (for static methods on class).

Upvotes: 4

Related Questions