Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java synchronization is doing auto notify on exit ? Is this expected?

Tags:

java

Java Question :

Coming out of synchronization block automatically does notifyAll(). Is that the expected behavior?

I have tested it and it seems like 1. when a execution comes out of sync block , it does auto notifyAll() 2. When method itself is synchronized , it does auto notify() when it returns.( not notifyAll() )

Code :

public class Test {

    public static void main(String[] args) throws InterruptedException {

        MyThread lock = new MyThread();

        new WatingThread(lock,1).start();
        new WatingThread(lock,2).start();

        //above tow threads would start and then wait for a lock 


        lock.start();

    }
}

class MyThread extends Thread {

    public void run() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("MyThread is trying to acquire the lock ..");
        synchronized (this) {
            System.out.println("MyThread has acquired the lock !!");

            System.out.println("MyThread is Coming out of synch block..");
        }
        System.out.println("MyThread has released the lock !!");

    }
}


class WatingThread extends Thread
{
    private Object lock;
    private int id;

    public WatingThread(Object lock, int id )
    {
        this.lock = lock;
        this.id = id;
    }

    @Override
    public void run() {
        System.out.println(String.format("[%d] : Check if lock is available ...",new Object[]{id}));
        synchronized (lock) {
            System.out.println(String.format("[%d] : Acquired the lock !!",new Object[]{id}));
            try {
                System.out.println(String.format("[%d] : Going to wait on lock.. ",new Object[]{id}));
                lock.wait();
                System.out.println(String.format("[%d] : Got notified !!!",new Object[]{id}));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(String.format("[%d] :I am done !!",new Object[]{id}));
        }
    }


}

Output:

[2] : Check if lock is available ...
[2] : Acquired the lock !!
[1] : Check if lock is available ...
[2] : Going to wait on lock..
[1] : Acquired the lock !!
[1] : Going to wait on lock..
MyThread is trying to acquire the lock ..
MyThread has acquired the lock !!
MyThread is Coming out of synch block..
MyThread has released the lock !!
[1] : Got notified !!!
[1] :I am done !!
[2] : Got notified !!!
[2] :I am done !!

like image 739
abhi Avatar asked Dec 26 '22 02:12

abhi


2 Answers

What you have discovered is that java.lang.Thread uses the wait facility internally using itself as a lock. This is documented in the description for the Thread.join() method (not the best place, probably):

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

By the way, if you used a while loop for checking if the condition for waiting has changed as the best practice dictates, that would guard you against such wakeups, though, of course, it is best to just use an Object as a lock anyway.

like image 63
Malcolm Avatar answered Apr 06 '23 01:04

Malcolm


You shouldn't use a Thread object as a locking object. See more explanations in question Does java notify waiting threads implicitly?.

Advertisement: Jon Skeet speaks there :) (This is a direct link to the answer in the above linked question.)

There is also another question linked from a comment, now I'll make it more achievable: who and when notify the thread.wait() when thread.join() is called?

like image 21
Jarekczek Avatar answered Apr 06 '23 01:04

Jarekczek