Home > Blockchain >  Why when using wait( ) , notify( ) , notifyAll( ) in java the thread using this part of code must be
Why when using wait( ) , notify( ) , notifyAll( ) in java the thread using this part of code must be

Time:12-30

The idea that when you remove the keyword synchronized when using wait( ) , notify( ) , notifyAll( ) it raises an error while running the program I know that wait( ) , notify( ) , notifyAll( ) must be included inside a synchronized block to make that thread using them the only thread owning the monitor on that pice of code but my question is : Why when using wait( ) , notify( ) , notifyAll( ) in java the thread using this part of code must be the only thread that own it's monitor ?

when remving the keyword synchronized from the pice of code that contains wait( ) , notify( ) or notifyAll() this raises an error while I found no logical reason for that error

CodePudding user response:

Requiring that the lock on the object is held resolves a race condition.

Imagine that synchronized is not needed:

  • Thread A checks a flag and decides it needs to wait
  • Thread B sets the flag
  • Thread B calls notify
  • Thread A actually calls wait

Now Thread A will wait forever.

With synchronized:

  • Thread A takes the lock
  • Thread B wants to set the flag, so tries to take the lock, but is blocked
  • Thread A checks the flag
  • Thread A calls wait (which releases the lock)
  • Now thread B can set the flag and call notify
  • Thread A wakes up and sees the flag is set.

CodePudding user response:

When using synchronized, you're in fact locking an object.

final Object lock = new Object();
// ...
synchronized (lock) {
    // ...
}

Only one thread at a time can lock onto that object. Unless you call wait(). If so, another thread is allowed for entering that critical section, doing it's stuff with that object and either calling wait() or notifying the other object holder(s) allowing them to continue past their wait() call.

void log(String message) {
    System.out.println("["   Thread.currentThread().getName()   "] "   message);
}

final int max = 10;
final Object valueLock = new Object();
volatile int value = 0;

Thread setupThread = new Thread(() -> {
    log("Started");
    for (int i = 0; i < max; i  ) {
        Thread valueThread = new Thread(() -> {
            log("Started");
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized(valueLock) {
                log(value   " -> "   (  value));
                valueLock.notifyAll();
            }
            log("Finished");
        });
        valueThread.start();
    }
    log("Finished");
}, "setupThread");

setupThread.start();

log("Waiting for the value to reach "   max);
synchronized(valueLock) {
    while (true) {
        if (value < max) {
            valueLock.wait();
        } else {
            break;
        }
    }
}
log("Finished");

Output:

[setupThread] Started
[Thread-0] Started
[Thread-1] Started
[Thread-2] Started
[Thread-3] Started
[Thread-4] Started
[Thread-5] Started
[Thread-6] Started
[Thread-7] Started
[Thread-8] Started
[setupThread] Finished
[Thread-9] Started
[Thread-2] 0 -> 1
[Thread-2] Finished
[Thread-6] 1 -> 2
[Thread-6] Finished
[Thread-4] 2 -> 3
[Thread-4] Finished
[Thread-5] 3 -> 4
[Thread-5] Finished
[Thread-1] 4 -> 5
[Thread-1] Finished
[Thread-0] 5 -> 6
[Thread-0] Finished
[main] Waiting for the value to reach 10
[Thread-7] 6 -> 7
[Thread-7] Finished
[Thread-8] 7 -> 8
[Thread-8] Finished
[Thread-3] 8 -> 9
[Thread-3] Finished
[Thread-9] 9 -> 10
[Thread-9] Finished
[main] Finished

Locking individual objects allows you for operating on more objects at a time.

https://onecompiler.com/jshell/3ytda2qwz

CodePudding user response:

In Java, the wait(), notify(), and notifyAll() methods can only be called from within a synchronized block or method. When a thread calls one of these methods, it must be the owner of the monitor for the object on which the method is called.

The reason for this is that these methods are used for inter-thread communication and synchronization, and they rely on the concept of monitors to ensure that only one thread can access a shared resource at a time. When a thread acquires the monitor for an object, it becomes the owner of the monitor and can use the wait(), notify(), and notifyAll() methods to communicate with other threads that may be waiting to acquire the monitor.

If a thread tries to call one of these methods while it is not the owner of the monitor, it will throw an IllegalMonitorStateException.

Here is an example of how you could use the wait(), notify(), and notifyAll() methods in a synchronized block:

synchronized (myObject) {
  // The current thread is now the owner of the monitor for myObject
  myObject.wait();
  // The current thread is now waiting for a notification from another thread
  // ...
  myObject.notify();
  // The current thread has notified one other waiting thread
  myObject.notifyAll();
  // The current thread has notified all waiting threads
}

I hope this helps!

  • Related