Sumith B
Sumith B

Reputation: 1

Reason for thread to enter blocked state when execution is in non synchronized section

I have two threads running: main and child thread. The activities they do are:

  1. Child thread counts the sum of 1 to 100.
  2. Main thread prints the total sum once it's calculated by child (so I used wait and notify). Also it outputs the child thread status.

So below is the code part.

class MainThread {
    public static void main(String[] args) throws InterruptedException {
        ThreadB b = new ThreadB();
        b.setName("Child thread: ");
        b.start();

        synchronized(b) {
            System.out.print("\nwaiting for b to complete\n");

            b.wait();

            System.out.print("\nno more wait .........................\n");
            for (int i = 0; i < 1000; i++)
                System.out.print("\n" + b.getName() + "'s state:" + b.getState());
        }
        Thread.sleep(1000);

        System.out.print("\n" + b.getName() + "state:" + b.getState());
        System.out.print("\ntotal in " + Thread.currentThread().getName() + "is :" + b.total);
    }
}

class ThreadB extends Thread {

    int total;

    public  void run() {
        synchronized(this) {
            for (int i = 0; i < 100; i++)
                total += i;
            System.out.println(this.getName() + "finished sum, lets notify other objects");

            notify();
            System.out.println(this.getName() + " done with notify and sync block\n");
        }

        System.out.println(this.getName() + " : entered non critical section"); 
        for(int j = 0; j < 1000; j++) {
            System.out.print("Hi ");
        }
    }
}
  1. Child finished its synchronized block and notified main thread. and even it's started non synced part which is nothing but printing "Hi " in loop.
  2. Now main thread after notified, resumed its work and prints child's status.

But here is my observation: while executing the "Hi " (for loop which is in non sync block), sometimes child's status is RUNNABLE and most of the times it's BLOCKED. For example:

Child thread: 's state:RUNNABLE Hi Hi Hi 

Child thread: 's state:BLOCKED Hi Hi Hi Hi    

What caused the child thread to enter in BLOCKED state when executing its non-synced block?

Upvotes: 0

Views: 960

Answers (4)

Solomon Slow
Solomon Slow

Reputation: 27190

I'm not sure I fully understand your question. Are you saying that the child thread hangs? (i.e., are you saying that it becomes BLOCKED forever?) If so, that's probably a lost notification.

Your program contains a data race. After the main thread calls b.start() the two threads race to synchronize on the new ThreadB object. If the ThreadB thread wins the race, it will enter the synchronized block, count up to 100, call this.notify() and then exit.

As soon as the ThreadB thread exits the synchronized block, then the MainThread thread is able to enter its synchronized block, and call b.wait(). The b.wait() call will never return because there's no other thread that will ever call b.notify(): The ThreadB thread is already done and gone by that point.

A call to b.notify() does not do anything at all if there is no other thread that is already waiting. The object, b, does not remember that it was notified.


The wait() and notify() methods are low level primitives that were meant to be used in a very specific way. See the Oracle Guarded Blocks Tutorial for more info.

Upvotes: 0

Gerald M&#252;cke
Gerald M&#252;cke

Reputation: 11132

The two threads do not synchronize each other on ThreadB but on the System.out Printstream's write method, which has a synchronized block so only one thread can write to the stream at a time.

public void write(int b) {
    try {
        synchronized (this) {
            ensureOpen();
            out.write(b);
            if ((b == '\n') && autoFlush)
                out.flush();
        }
    }

Upvotes: 0

Rett Pop
Rett Pop

Reputation: 3

Sometimes ThreadB runs faster than main thread and gets synchronized (this) first. In this case it should work by your scenario. But sometimes main thread runs in synchronized(b) faster. And then ThreadB gets blocked by main thread that, in turn, waits for notification from b. Try to remove synchronized block from main thread and relay only on b.wait().

Upvotes: -1

David Schwartz
David Schwartz

Reputation: 182827

Two threads cannot print to the same device at the same time. If they try, one of them will have to be blocked.

Upvotes: 4

Related Questions