2

The message "main Thread" is printed before message "new Thread" though method with message "new Thread" is in syncronized section by object which include print* methods.

    Test test = new Test();
    new Thread(() -> {
        try {
            synchronized (test) {
                Thread.sleep(5000);
                test.printMessage();
            }
        } catch (InterruptedException e) {}
    }).start();
    Thread.sleep(1000);
    test.printAnotherMessage();
}

public void printMessage() {
    System.out.println("new Thread");
}

public void printAnotherMessage() {
    System.out.println("main Thread");
}

}

Jara G
  • 33
  • 5
  • Only, explicit synchonizations (synchonized method or synchonized statement) on an instance makes threads to require to get the monitor on that object to execute the synchronized code. – davidxxx Sep 20 '19 at 10:29
  • The other thread is not going into any `synchronized` blocks. You need to have those on both sides. – Thilo Sep 20 '19 at 10:39

2 Answers2

3

In this example there is no synchronization between printAnotherMessage and the synchronized block that sleeps for 5 seconds, that's why main thread sleeps for 1 second and then prints main Thread without any waiting.

You probably intended to make printAnotherMessage a synchronized method. In this case main thread will wait till the other thread finishes the execution of the block synchronized on test object.

  • I thought that "synchronized(object)" blocks access to any members of that object no matter synchronized or not – Jara G Sep 20 '19 at 10:40
  • @JaraG, You and many other beginners. But that's not what it does. It only prevents other threads from synchronizing on the same object at the same time. (IMO: This is just one of several Java features whose use or meaning is obvious to experts, but which were named or designed in a way that is confusing to beginners.) – Solomon Slow Sep 20 '19 at 13:30
2

There is no synchronisation on test.printAnotherMessage(); so it will be executed first assuming the timing is right. 4 seconds is a lot and should be enough.

synchronized (test) {
    test.printAnotherMessage();
}

Thread.sleep is rarely a good option, though. A more proper way would be

Test test = new Test();

new Thread(() -> {
    synchronized (test) {
        test.printMessage();
        test.notify();
    }
}).start();

synchronized (test) {
    test.wait();
    test.printAnotherMessage();
}

I am playing a dangerous game here since I am assuming the main thread will enter the synchronized block and execute wait() before another thread is created and it enters its synchronized block. It's reasonable since creating a thread will take some time.

Test test = new Test();
new Thread(() -> {
    try {
        // a lot of time to let the main thread execute wait()
        Thread.sleep(500); 

        synchronized (test) {
            test.printMessage();
            test.notify();
        }
    } catch (InterruptedException e) {}
}).start();

synchronized (test) {
    test.wait();
    test.printAnotherMessage();
}
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142