How synchronized is working in the following threading code and what is the code flow?

70 Views Asked by At
class ThreadA {
public static void main(String[] args) {
    ThreadB b = new ThreadB();
    b.start();
    synchronized (b) {
        try {
            System.out.println("Waiting for b to complete...");
            b.wait();
        } catch (InterruptedException e) {
        }
        System.out.println("Total is: " + b.total);
    }
}}

class ThreadB extends Thread {
int total;

public void run() {
    synchronized (this) {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
        notify();
    }
}}

I am unable to understand the code flow and how run method is being called in the above programs. When the object is of class ThreadB then why main() thread of ThreadA is able to synchronize object b. Apart from that when wait() is encountered by the main() thread, how the executions shifts to run() in ThreadB.

2

There are 2 best solutions below

2
On

Why does main() reaches to the synchronized block even before ThreadB's run() is able to execute.

Your program has a race condition.

After main() calls b.start() there are two threads running, unsynchronized, and they race to lock (i.e., synchronize on) the b object. There is no way to predict which thread will lock it first.

If the main() thread locks it first, then it will call b.wait(). That will temporarily unlock the b object, and allow the other thread to run. The other thread will do its work, call b.notify() and exit the synchronized block. As soon as it exits, the main() thread will be able to return from the wait() call.

If the second thread is first to lock the b object, the behavior will be different: It will do its work, call notify(), and return. But the notify() call will do nothing in that case because the main() thread will be blocked trying to enter the synchronized block. It won't be waiting in the b.wait() call, and notify() doesn't do anything if there isn't any other thread waiting.

So what will happen next in that case is, when the ThreadB thread leaves the synchronized block, the main() thread will be able to enter it and call wait(). The program will hang at that point because the ThreadB thread has already finished its work and died. There's no other thread left to call notify().

We call it a race condition when two (or more) threads race to do something, and the output of the program depends on which one gets there first.

2
On

Apart from that when wait() is encountered by the main() thread, how the executions shifts to run() in ThreadB.

Before invoke wait()

If it will invoke wait method next step, It means main thread hold monitor of object b currently. And if threadB want to execute run() method it will be blocked for waiting monitor of b which is hold by main thread.

invoke wait()

It means main thread release monitor, come into wait status, and advice thread scheduler re_dispatch. Then ThreadB can get monitor and make thing.

notify()

after finishing its job, threadB invoke notify() to wake up a single thread that is waiting on this object's monitor, here is main thread. And main thread will go on doing its work.