-2

The following code does not get notify the thread reader it execute the writer and then terminates. Why is it like that? The notifyall should awake all the thread which are at the wait state.

public class Testing {

    public static void main(String[] args) {
        Testing testing=new Testing();
        testing.reader.start();
        testing.writer.start();
    }
    Thread reader = new Thread("reader") {
        public void run() {

            System.out.println("reader started");

            synchronized (this) {
                try {

                    wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("reader " + i);

            }
        }

    };
    Thread writer = new Thread("writer") {
        public void run() {
            System.out.println("writer started");

            for (int i = 0; i < 10; i++) {
                System.out.println("writer " + i);
            }
             synchronized (Thread.currentThread()) {
                 notifyAll();
            }

        }

    };

}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • yes the reader thread is returned while calling current thread.But neither the notify and notifyall doesnt wakeup the waiting thread. – Midhun Krishna May 08 '17 at 09:16
  • oops! that was a mistake.I will correct that to writer.Actually now the current thread returned is writer.Can you help me to understand how can I notify the reader thread. – Midhun Krishna May 08 '17 at 09:18
  • Never call `wait` without first confirming, inside the `synchronized` block, that the thing you are waiting for hasn't already happened. And never leave the `synchronized` block after calling `wait` without confirming that the thing you are waiting for has happened. (Also, your writer calls `notifyAll` without having changed anything inside the `synchronized` block, so there's nothing to notify about.) – David Schwartz May 08 '17 at 16:54

3 Answers3

0

NotifyAll () does not belong to the Thread class, but belongs to the Object base class;in the thread writer , notifyAll() is the function of writer Object , it can
awake the thread which has the writer Object lock ; enter image description here

handsp
  • 127
  • 5
0

The following code does not get notify the thread reader it execute the writer and then terminates. Why is it like that?

Your program does not finish because the writer thread terminates but the reader thread is stuck in wait(). The problem with your code is that the reader thread is waiting on it's own thread object while the writer thread is notifying on it's own thread object which is different. What you need to do is to have each of them wait and notify on the same object instance.

A quick fix would be to use a static lock object:

private static final Object lockObject = new Object();
// reader:
synchronized (lockObject) {
    lockObject.wait();
...
// writer
synchronized (lockObject) {
    lockObject.notify();

Then both the reader and writer are locking, waiting, and notify-ing on the same final object instance. It is a good pattern to synchronize on fields that cannot be changed so private final Object or some such is best. Also, you only have one thread so notify() is enough.

However, your code still suffers from race condition issues. It is possible (albeit unlikely) for your writer to call notifyAll() before the reader gets to the wait(). If the notify happens and there is no one waiting then it is a noop and the reader will hang when it gets to the wait().

A better solution would be to use a shared AtomicBoolean:

private final AtomicBoolean writerDone = new AtomicBoolean();
...
// reader
while (!writerDone.get()) {
    synchronized (writerDone) {
        writerDone.wait();
    }
}
// writer
writerDone.set(true);
synchronized (writerDone) {
    writerDone.notifyAll();
}
Gray
  • 115,027
  • 24
  • 293
  • 354
0

you just do little change, as follow:

public static void threadTest(){
        Test testing = new Test();
        testing.lock = new Object();
        testing.reader.start();
        testing.writer.start();
    }
    private  Object lock;
    Thread reader = new Thread("reader") {
        public void run() {

            System.out.println("reader started");

            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("reader " + i);

            }
        }

    };
    Thread writer = new Thread("writer") {
        public void run() {
            System.out.println("writer started");

            for (int i = 0; i < 10; i++) {
                System.out.println("writer " + i);
            }
            synchronized (lock) {
                lock.notifyAll();
            }

        }

    };
handsp
  • 127
  • 5