Java: wait(), notify() and nested synchronized blocks [duplicate] - java

This question already has answers here:
Java: Are all monitors released when thread waits on an object?
(3 answers)
Closed 8 years ago.
Will this work or result in deadlock?
thread 1:
synchronized (globalLock) {
synchronized (o) {
o.wait();
}
}
thread 2 (later):
synchronized (globalLock) {
synchronized (o) {
o.notify();
}
}
So from what I understand, o.wait() will release the lock of o, but will it release the lock of globalLock? Probably not and this will result in deadlock?

As mentioned in comments, this is trivially easy to test. Yes, it does deadlock for the reasons you guessed.
public static void main(String[] args) throws InterruptedException {
final Object globalLock = new Object();
final Object o = new Object();
new Thread(new Runnable() {
#Override
public void run() {
synchronized (globalLock) {
synchronized (o) {
try {
System.out.println("waiting");
o.wait();
} catch (InterruptedException ie) {
// no-op
}
}
}
}
}).start();
Thread.sleep(2000); // ensure thread above starts first
new Thread(new Runnable() {
#Override
public void run() {
synchronized (globalLock) {
synchronized (o) {
System.out.println("notifying");
o.notify();
}
}
}
}).start();
}

Yes deadlock when Thread 1 started before Thread2.
Thread 2 will never be able to execute its :
synchronized (globalLock)
because Thread 1 has never come out of synchronized (globalLock)

Related

Why does the wait() method not trigger notifyAll()? [duplicate]

This question already has answers here:
Understanding wait() and notify() methods
(2 answers)
Closed 12 months ago.
I'm new to Java multithreading and written a small program to test how the wait() and notifyAll() methods interact with each other. But why doesn't this program work?
package sample;
public class Main {
public static void main(String[] args) {
new Thread(new MyWriter()).start();
new Thread(new MyReader()).start();
}
}
class MyReader implements Runnable {
#Override
public synchronized void run() {
while(true) {
notifyAll();
}
}
}
class MyWriter implements Runnable {
#Override
public synchronized void run() {
while(true) {
try {
System.out.println("Waiting...");
wait();
System.out.println("Wait Terminated");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
When running, I expected the output to be
Waiting...
Wait Terminated
But it outputs
Waiting...
And just waits forever until I terminate it manually.
A notify call notifies the objects waiting on the monitor of an object. So, if you issue wait on an object, you have to notify using the same object.
One way to do this is to simply use a shared object:
public static void main(String[] args) {
Object lock=new Object();
new Thread(new MyWriter(lock)).start();
new Thread(new MyReader(lock)).start();
}
Then:
public void run() {
while(true) {
synchronized(lock) {
lock.notifyAll();
}
}
public void run() {
while(true) {
try {
synchronized(lock) {
System.out.println("Waiting...");
lock.wait();
System.out.println("Wait Terminated");
}
} ...
}

Why am I getting IllegalMonitorStateException for the Thread t1

I'm getting this error for the code below
First thread about to sleep
thread 1 run
Boolean assignment done.
Woke up and about to invoke wait()
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at IncorrectSynchronization$1.run(HelloWorld.java:23)
at java.lang.Thread.run(Thread.java:748)
When the Thread t1 is sleeping, I modified the lock to false from another thread.
It then throws this IllegalMonitorStateException. It's still the same object, why would modifying the value cause IllegalMonitorStateException?
When I modify the lock to false from another thread inside a synchronized block, I no longer get that error. Can anyone explain the reason for what's happening under the hood?
public class HelloWorld{
public static void main( String args[] ) throws InterruptedException {
SampleTest.runExample();
}
}
class SampleTest{
Boolean flag = new Boolean(true);
public void example() throws InterruptedException {
Thread t0 = new Thread(new Runnable() {
public void run() {
synchronized (flag) {
try {
while (flag) {
System.out.println("First thread about to sleep");
Thread.sleep(2000);
System.out.println("Woke up and about to invoke wait()");
flag.wait();
System.out.println("wait() called");
}
} catch (InterruptedException ie) {
}
}
}
});
Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println("thread 1 run");
flag = false;
}
});
t0.start();
Thread.sleep(200);
t1.start();
t0.join();
t1.join();
}
public static void runExample() throws InterruptedException {
SampleTest test = new SampleTest();
test.example();
}
}
The problem is with this line:
flag = false;
This changes the reference of the flag Boolean variable, from the original Boolean object (which is created by the deprecated constructor which should not be used) to the pre-created Boolean.FALSE instance (due to autoboxing). By the time the first thread calls flag.wait(), the object is no longer the same as the one it used to synchronize, hence the IllegalMonitorStateException.
In this scenario, it's much better to use an AtomicBoolean and mutate its value in the other thread:
AtomicBoolean flag = new AtomicBoolean(true);
Now the second thread can update the value of the same object. It should also probably notify the first thread that is waiting on the object (like wait(), notify() also requires synchronizing on the object on which it is invoked):
Thread t1 = new Thread(new Runnable() {
public void run() {
synchronized(flag) {
System.out.println("thread 1 run");
flag.set(false);
flag.notify();
}
}
});

Print odd & even number using Multi threading [duplicate]

This question already has answers here:
IllegalMonitorStateException on wait() call
(12 answers)
Closed 5 years ago.
I am trying to learn Multi threading and for practice, I am trying to print odd & even number using two thread. I have created an object which will act as a lock for the both the threads. When I try to execute it throws java.lang.IllegalMonitorStateException.
class EVENODDimpl implements Runnable {
int num;
int temp = 0;
Object lock = new Object();
public EVENODDimpl( int num) {
this.num = num;
}
public void run() {
try {
synchronized (lock) {
while(temp<num) {
temp++;
System.out.println(Thread.currentThread().getName()+" "+temp);
this.notify();
this.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main Method:
public class EVENODD {
public static void main(String[] args) {
int i = 10;
EVENODDimpl ei = new EVENODDimpl(i);
Thread t1 = new Thread( ei,"EvenThread");
Thread t2 = new Thread( ei,"OddThread");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You wait and notify on this, but you should wait and notify on lock because you synchronize on lock, you can't wait and notify on other object than the one on which you're synchronizing, working version:
class EVENODDimpl implements Runnable {
int num;
int temp = 0;
Object lock = new Object();
public EVENODDimpl( int num) {
this.num = num;
}
public void run() {
try {
synchronized (lock) {
while(temp<num) {
temp++;
System.out.println(Thread.currentThread().getName()+" "+temp);
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
As it said from the javadoc
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
This means that your methods notify and wait should own monitor. Or in other words the object that is calling these method must be synchronized. Your this object is not synchronized. That's why you get this exception. Call this method from lock object in your case.
Your logic is still wrong but it is up to you to explore that.
java.lang.IllegalMonitorStateException Exception occur because you are using notify method on the object this.notify() but that Object is not synchronized.
Replace synchronized (lock) with this: synchronized (this)

can not reproduce deadlock using the next code

can not reproduce deadlock using the next code
I am trying yo get a deadlock using the next code,
but it seems that it works good.
Please see below:
public class Deadlock {
static Object lock1 = new Object();
static Object lock2 = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
synchronized (lock1) {
System.out.println("Thread 1: locked lock1");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 1: locked lock2");
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
synchronized (lock2) {
System.out.println("Thread 2: locked lock2");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("Thread 2: locked lock1");
}
}
}
}).start();
}
}
What I don't understand in this case or what's wrong in this code?
To cause a deadlock, you need to hold both locks in these threads in reverse order.
// thread 1
public void run() {
synchronized (lock1) {
synchronized (lock2) {
// do something
}
}
}
// thread 2
public void run() {
synchronized (lock2) {
synchronized (lock1) {
// do something
}
}
}
This is necessary, but not sufficient. To be able to simulate the deadlock, you need to make sure both threads acquire their first locks respectively successfully before attempting to acquire the next.
Why would the above code cause a deadlock? Each thread only locks one lock at a time, so if the other thread tries to lock it, it just has to wait for the first one to release it.
You would have a serious risk of deadlock if the threads did
synchronized (lock1) {
synchronized (lock2) {
...
}
}
and
synchronized (lock2) {
synchronized (lock1) {
...
}
}
Your code will never "dead lock".
To dead lock, you must lock the other lock within a lock.
To get a deadlock you need to hold two locks at once. You can hold the first lock for the whole loop.
If you are trying to get a deadlock, you need to nest the synchronized blocks so that you attempt to whole both locks simultaneously:
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
synchronized (lock1) {
System.out.println("Thread 1: locked lock1");
try {
// Sleep to allow Thread2 to obtain lock2
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 1: locked lock2");
}
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
// Sleep to allow Thread1 to obtain lock1
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 2: locked lock2");
synchronized (lock1) {
System.out.println("Thread 2: locked lock1");
}
}
}
}
}).start();
Note that the locks are acquired in reverse order, with sleeps to ensure the following acquisition order:
Thread 1 acquires lock1
Thread 2 acquires lock2
Thread 1 attempts to acquire lock2 <--- DEADLOCK
Thread 2 attempts to acquire lock1 <--- DEADLOCK
Note that the last two can happen in either order, but the deadlock will occur regardless.
Have the second thread try to get a lock on lock1. That's the classic way to invoke deadlock. Two resources locked in different orders.
Sorry... didn't scroll down far enough in your code... feeling foolish

Understanding Java Wait and Notify methods

I have a following program:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleWaitNotify implements Runnable {
final static Object obj = new Object();
static boolean value = true;
public synchronized void flag() {
System.out.println("Before Wait");
try {
obj.wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
System.out.println("After Being Notified");
}
public synchronized void unflag() {
System.out.println("Before Notify All");
obj.notifyAll();
System.out.println("After Notify All Method Call");
}
public void run() {
if (value) {
flag();
} else {
unflag();
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(4);
SimpleWaitNotify sWait = new SimpleWaitNotify();
pool.execute(sWait);
SimpleWaitNotify.value = false;
SimpleWaitNotify sNotify = new SimpleWaitNotify();
pool.execute(sNotify);
pool.shutdown();
}
}
When I wait on obj, I get the following exception Exception in thread "pool-1-thread-1" java.lang.IllegalMonitorStateException: current thread not owner for each of the two threads.
But if I use SimpleWaitNotify's monitor then the program execution is suspended. In other words, I think it suspends current execution thread and in turn the executor. Any help towards understanding what's going on would be duly appreciated.
This is an area1 where the theory and javadoc seem straightforward, and since there aren't many examples, conceptually left a big gap in me.
You're calling wait and notifyAll on obj, but you're synchronizing on this (because you've got synchronized methods).
In order to wait or notify, you need to "own" the monitor first. Unsynchronize the methods, and synchronize on obj instead:
public void flag() {
System.out.println("Before Wait");
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
}
System.out.println("After Being Notified");
}
public void unflag() {
System.out.println("Before Notify All");
synchronized (obj) {
obj.notifyAll();
}
System.out.println("After Notify All Method Call");
}
Either synchronize on obj, or call wait and notify on this. The calling thread must hold the monitor of the same object on which these methods are called.
For example,
synchronized void flag() {
System.out.println("Before Wait");
try {
wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
System.out.println("After Being Notified");
}
In this example, the lock is held on this (when the modifier synchronized is used on a instance method, the monitor of the instance is acquired). So, the wait() method may be invoked on the implied instance this.
In order to coordinate the two threads, they need to share the same lock. The original version had a static obj that could be used as a lock, but it wasn't used in the synchronized blocks. Here is a better example:
class SimpleWaitNotify implements Runnable {
private final Object lock;
private final boolean wait;
SimpleWaitNotify(Object lock, boolean wait) {
this.lock = lock;
this.wait = wait;
}
public void flag() {
synchronized (lock) {
System.out.println("Before Wait");
try {
lock.wait();
System.out.println("After Being Notified");
} catch (InterruptedException ex) {
System.out.println("Thread interrupted");
}
}
}
public void unflag() {
synchronized(lock) {
System.out.println("Before Notify All");
lock.notifyAll();
System.out.println("After Notify All Method Call");
}
}
public void run() {
if (wait) {
flag();
} else {
unflag();
}
}
public static void main(String[] argv) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(4);
Object shared = new Object();
SimpleWaitNotify sWait = new SimpleWaitNotify(shared, true);
pool.execute(sWait);
SimpleWaitNotify sNotify = new SimpleWaitNotify(shared, false);
pool.execute(sNotify);
pool.shutdown();
}
}
Rather putting the direct statement pool.shutdown(), try as below.
while (!service.isTerminated())
{
service.shutdown();
}
So it will wait for till all the threads execution completes.

Categories