Java Thread never receiving notify - java

I've been trying to make a simple Java thread application, where one thread waits, and another wakes it up after 3 seconds. However, I can't seem to make it work and I just can't figure out why.
public class Deadlock extends Thread {
Object lock = new Object();
public static void main(String[] args) {
//WAITER THREAD
Deadlock waiter = new Deadlock() {
#Override
public void run() {
System.out.println("Waiter started");
synchronized(lock) {
try{
System.out.println("Waiter will wait for notify...");
lock.wait();
System.out.println("Woke up!");
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}//run()
};
//WAKER THREAD
Deadlock waker = new Deadlock() {
#Override
public void run() {
System.out.println("Waker started");
synchronized(lock) {
System.out.println("Waker sleeping for 3 seconds.");
try{
Thread.sleep(3000);
}catch(InterruptedException e) {}
System.out.println("Waker notifying...");
lock.notifyAll();
}
}//run
};
waiter.start();
waker.start();
}
}
The output I get is:
Waiter started
Waiter will wait for notify...
Waker started
Waker sleeping for 3 seconds.
Waker notifying...
...and keeps running forever. I expected the waiter thread to wake up and the program to terminate.
Thanks

Your main problem is that the 'lock' is a class instance property so the two Deadlock instances do not share the same 'lock'. Hence, calling notifyAll() in the waker has no effect on the waiter because it's waiting on a different object. The simplest solution is to make 'lock' static:
static Object lock = new Object();
... I'd also make it private and final for good measure.
The second issue is that by starting the two threads together you don't really guarantee that the waiter will run first - I'd add a short delay before starting the waker.

Related

Using synchronized blocks, notify() and wait() the right way

I'm curious to submit here a short example I made and hopefully have someone able to explain to me one thing: is it possible to use the wait() and notify() inside a synchronized block without having to declare threads explicitly? (AKA: not using dedicated threads).
Here's the example:
public class mutex {
private Object mutex = new Object();
public mutex(Object mutex) {
this.mutex = mutex;
}
public void step1() throws InterruptedException {
System.out.println("acquiring lock");
synchronized(mutex) {
System.out.println("got in sync block");
System.out.println("calling wait");
mutex.wait();
System.out.println("wait finished ");
}
}
public void step2() throws InterruptedException{
System.out.println("acquiring lock");
synchronized(mutex){
System.out.println("got in sync block");
System.out.println("calling notify");
mutex.notify();
System.out.println("notify called");
}
}
Those two simple step are just prints for logging and what should be happening.
The idea is to be able to call a wait() in step1 and be able to complete the call once step2 has been called with its notify().
Now, as far as I understood the whole thing, this is the right way to do what I want to do:
public void go1() {
Object mutex = new Object();
mutex m = new mutex(mutex);
Thread t1 = new Thread(()->{
try {
m.step1();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
try {
Thread.sleep(1000);
m.step2();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
and finally the main
public static void main(String[] args) {
Object mutex = new Object();
new mutex(mutex).go1();
//new mutex(mutex).go2();
}
The above code works and shows what I am expecting:
acquiring lock
got in sync block
calling wait
acquiring lock
got in sync block
calling notify
notify called
wait finished
I get why it works. This is what I expected to happen and how I have been taught to do this. The question comes now as I will paste the second variant of the main function I wanted to test - this one just hangs when the wait() is called.
public void go2() {
Object mutex = new Object();
mutex m = new mutex(mutex);
try {
m.step1();
Thread.sleep(1000);
m.step2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Why does this hang?
Is it because there is just one thread doing everything and it goes into waiting state after the wait() is called?
I know that when wait is called on the monitor object it should also release the lock, so why in this case the program can't get to call the step2()?
Is there a way to use the my second go() function to achieve this process or is it impossible for it to work?
TLDR just so I am making sure I can be understood: do I have to use dedicated threads to also use properly wait() and notify()? Because I seem to get deadlocks if I don't.
Thank you.
Once you call mutex#wait, the current thread is added to the wait set of object mutex. And thread will not execute any further instructions until it has been removed from mutex's wait set. That's why step2 cannot be executed by the current thread.
The current thread will be removed from the wait set and resume if other threads call mutex#notify/notifyAll. See JLS#WAIT for all situations in which the current thread can resume..

Threads logic in Java

I'm trying to resolve a university exercise. The class AImpl has a method ma(B b) that creates and runs two threads. These threads have to call mb1() and mb2() (they are simple methods that just print a text, so I didn't include them). The calling thread should then wait for mb1() to terminate before finishing.
My logic is:
The first thread enters and after finishing the execution of b.mb1() starts to wait() on the current object, releasing the mutex. Then the second thread runs and it does the same. When they are both waiting, the calling thread calls notifyAll() on the object, waking both of them. They execute b.mb2() and then terminate.
The problem is that when the first thread starts waiting with object.wait(), the control flow doesn't return on the calling thread and the program enters in a deadlock.
Where is my logic flawed?
public class AImpl{
public static Object object = new Object();
public static void main(String[] args) throws InterruptedException {
BImpl b = new BImpl();
AImpl.ma(b);
}
public static void ma(B b) throws InterruptedException {
Thread thread = new Thread() {
#Override
public void run() {
b.mb1();
synchronized(object){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
b.mb2();
System.out.println("Thread finished");
}
};
Thread thread1 = new Thread() {
#Override
public void run() {
b.mb1();
synchronized(object){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
b.mb2();
System.out.println("Thread finished");
}
};
thread.run();
thread1.run();
synchronized(object){
object.notifyAll();
}
System.out.println("Program finished.");
}
}
The notify/notifyAll methods tell the scheduler to notify one/all of the threads currently waiting on the lock that notify or notifyAll was called on. But if a thread hasn't started waiting yet then it doesn't get notified.
The solution is to introduce a condition variable that keeps wait from being called if the notifying has happened already. Define it in the same scope as your lock:
public static volatile boolean ready = false;
Then use it to guard the wait block, like this:
while (!ready) {
object.wait();
}
The code calling notify/notifyAll needs to set the variable (it doesn't matter what order you do it in because the notification doesn't happen until the lock is released):
synchronized (object) {
ready = true;
object.notifyAll();
}
What happens:
If the waiting thread gets to the waiting part before the notifying thread does its notifying, then the waiting thread finds ready is false, so it enters the wait method, releases the lock, and stays there. Then the notifying thread changes the flag to true and wakes up the waiting thread, which can leave the wait, reacquire the lock, and then leave the loop now that the flag is set.
But if the notifying thread does its notify before the other thread waits, that's ok, because the ready flag now prevents the thread from entering the wait, it can skip over it.
Further reading: https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

Join one of any threads in Java

In my Java program, I will launch two Threads simultaneously. I want for my program to join() on either one of two threads's completion without waiting for both threads to complete. In other words, if thread A finishes before thread B, I want the main thread to join thread A and resume the main thread without waiting for Thread B to finish and vice versa.
Which of those Java classes that allows me to do this?
One solution to accomplish that is with a CountDownLatch, by having the main thread wait for its count to reach zero, and having the two threads each decrease the count (the initial value of the count would be 1 in this case).
public static void main(String[] atrgs){
Thread t1 = new Thread(new MyRunnable());
Thread t2 = new Thread(new MyRunnable());
t1.start();
t2.start();
while(t1.isAlive()&&t2.isAlive()){
}
System.out.println("main resumes");
}
Actually, any class in Java allows you to do that since an object of any class can be used as a monitor for waiting a notification. Just create an object, call wait() on it and make your threads notify on this object when finished:
private class Foo implements Runnable {
private final int id;
private final Object monitor;
public Foo(int id, Object monitor) {
this.id = id;
this.monitor = monitor;
}
#Override
public void run() {
try {
Thread.sleep((long)(Math.random() * 10000));
} catch (InterruptedException e) {
}
System.out.println(id + " finished");
synchronized (monitor) {
monitor.notify();
}
}
}
public static void main(String[] args) throws InterruptedException {
final Object monitor = new Object();
synchronized (monitor) {
new Thread(new Foo(1, monitor)).start();
new Thread(new Foo(2, monitor)).start();
System.out.println("Main goes to sleep");
monitor.wait();
}
System.out.println("Main is running");
}
The first notification will unblock the main thread and it will continue running.
I would say that this is a classic solution for your problem, though the solution that #AR.3 suggested will be less wordy and will surely work. I just wanted to show that even a simple monitor object is enough to do what you want.

Deadlocks using wait and notify

I am trying to understand how deadlocks are created. I've understood that by using two threads on two synchronized methods, a deadlock can be created.
Went through many examples from the net.
Can a deadlock be created with wait and notify?
Every time a thread is on wait, it will be notified. So how does this end up in a deadlock?
Illustration of an example will be helpful.
Deadlock is caused when two threads try to obtain the same, multiple locks in different order:
// T1
synchronized (A) {
synchronized (B) {
// ...
}
}
// T2
synchronized (B) {
synchronized (A) {
// ...
}
}
The only way to prevent deadlocks is to make sure that all threads obtain locks in the same order--either they all do A then B, or they all do B then A.
If you don't have multiple locks, then you don't have a deadlock. However, you can get thread starvation or other things that may look similar to deadlock.
Say thread 1 enters a synchronized block on method A and then waits. Thread 2 then attempts to enter the synchronized block on method A. Thread 1 is waiting for a notify, and thread 2 is waiting on the synchronized block. Everything is now waiting. Some other thread will have to notify the object on which thread 1 is waiting. This is just one scenario that can create a deadlock. There are all kinds of ways to do it.
A thread which is on wait will not be notified unless some code explicitly notifies it. Therefore the example you are looking for is absolutely trivial:
public static void main(String[] args) {
synchronized(String.class) {
String.class.wait();
}
}
and this hangs forever. Technically, though, it is not a deadlock, which requires two or more threads involved in a closed cycle where each thread waits for the next one to unblock it.
Something close to wait/notify deadlock:
public class Example
{
volatile boolean isNotified = false;
public synchronized void method1() {
try
{
isNotified = false;
while (!isNotified)
wait();
notifyAll();
System.out.println("Method 1");
} catch (InterruptedException e) {/*NOP*/}
}
public synchronized void method2() {
try {
isNotified = true;
while (isNotified)
wait();
notifyAll();
System.out.println("Method 2");
} catch (InterruptedException e) {/*NOP*/}
}
public static void main(String[] args)
{
Example example = new Example();
Thread thread1 = new Thread()
{
public void run()
{
example.method1();
}
};
Thread thread2 = new Thread()
{
public void run()
{
example.method2();
}
};
thread1.start();
thread2.start();
}
}

About wait and notifyAll

I've this class:
public class MyThread implements Runnable {
private static boolean canAccess = true;
private Thread t;
public FirstThread(String name) {
t = new Thread(this);
t.setName(name);
}
public void start() {
t.start();
}
private synchronized void accessed(String name) throws InterruptedException {
if (canAccess) {
canAccess = false;
System.out.println("Accessed " + name);
try {
Thread.sleep(5000);
} catch (Exception e) {
}
canAccess = true;
System.out.println("NOTIFY: " + name);
notifyAll();
}
System.out.println("WAIT: " + name);
wait();
}
#Override
public void run() {
while (true) {
try {
accessed(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And this is my output:
Accessed 1
WAIT: 3
WAIT: 5
WAIT: 7
WAIT: 9
WAIT: 0
WAIT: 2
WAIT: 4
WAIT: 6
WAIT: 8
NOTIFY: 1
WAIT: 1
and my app freeze (deadlock state).
Seems that the notifyAll method doesn't work. Where is my error?
My Main class.
public class Main {
public static void main(String[] args) {
MyThread [] threads = new MyThread[10];
for(int i=0;i<threads.length;i++) {
threads[i] = new MyThread(""+i);
threads[i].start();
}
}
}
wait means that the thread releases the lock and goes into a dormant state until another thread notifies it. notifyAll means that the thread tells all the other threads waiting on the lock being used in the current synchronized block to wake up and try to acquire the lock again. Your code example doesn't have any cases where multiple threads are trying to acquire the same lock so using wait and notifyAll here doesn't make any sense. There's nothing to wake up the thread once it calls wait.
One typical use of wait and notify: You might have many producers putting stuff in a queue, and consumer threads that take stuff out of the queue. The queue has a take method that the consumer calls, if the queue is empty then it calls wait and the consumer blocks. The queue has a put method that calls notifyAll when something goes into the queue so that any waiting consumer threads wake up.
There's a producer-consumer example of using wait and notifyAll in the Java tutorial.
Every Thread waits on it's own instance, that's why they all are stuck in one place.
If you had a private static Object LOCK = new Object(); and call LOCK.wait(); and LOCK.notify(); this could be another story.
I have also doubts about synchronized modifier for accessed() method. It's just doesn't have use in the described situation. I would better modify the "canAccess" variable in synchronized block.

Categories

Resources