I have the following simple code in which I put and take from a Queue represented as an ArrayList.
public class EmailService {
private Queue<Email> emailQueue;
private Object lock;
private volatile boolean run;
private Thread thread;
public void sendNotificationEmail(Email email) throws InterruptedException {
emailQueue.add(email);
synchronized (lock) {
lock.notify();
lock.wait();
}
}
public EmailService() {
lock = new Object();
emailQueue = new Queue<>();
run = true;
thread = new Thread(new Runnable() {
#Override
public void run() {
while (run) {
System.out.println("ruuuning");
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (emailQueue.getSize() > 0) {
sendEmail(emailQueue.poll());
}
lock.notify();
}
}
}
private void sendEmail(Email email) {
System.out.println("Sent email from " + email.getFrom() + " to " + email.getTo() + " with content: " + email.getContent());
}
});
thread.start();
}
public void close() throws InterruptedException {
run = false;
synchronized (lock) {
lock.notify();
System.out.println("Thread will join " + thread.isInterrupted());
thread.join();
System.out.println("Thread after join");
}
}
}
I don't understand why my thread is blocked in join() method.
From main I call as follow:
eService = new EmailService();
Email e1 = new Email(client1, client2, "content1");
eService.sendNotificationEmail(e1);
eService.close();
Without running it...
The close() method holds lock at the time it calls thread.join() and waits on thread (forever)
thread is waiting to reacquire lock so cannot run
Both are now waiting on each other, this is a deadlock. Try moving the Thread.join() after the synchronized block:
public void close() throws InterruptedException {
run = false;
synchronized (lock) {
lock.notify();
System.out.println("Thread will join " + thread.isInterrupted());
}
thread.join();
System.out.println("Thread after join");
}
#drekbour explained how your program could hang in the join() call, but FYI: Here's a different way that your program could hang. This is called lost notification.
Your main thread creates a new EmailService instance. The new instance creates its thread and calls thread.start() *BUT* it could take some time for the thread to actually start running. Meanwhile...
Your main thread creates a new Email instance, and calls eService.sendNotificationEmail(...). That function adds the new message to the queue, locks the lock, notifies the lock, and then waits on the lock.
Finally, The service thread starts up, enters its run() method, locks the lock, and then it calls lock.wait().
At this point, the program will be stuck because each thread is waiting to be notified by the other.
The way to avoid lost notification is, in the consumer thread, do not call wait() if the thing that you are waiting for already has happened.
synchronized(lock) {
while (theThingHasNotHappenedYet()) {
lock.wait();
}
dealWithTheThing();
}
In the producer thread:
synchronized(lock) {
makeTheThingHappen();
lock.notify();
}
Notice how both threads lock the lock. Ever wonder why lock.wait() throws an exception if the lock isn't locked? The examples above illustrate why. The lock prevents the producer thread from making the thing happen after the consumer already has decided to wait. That is key: If the consumer were to wait after the producer calls notify() then it's game over. The program hangs.
Related
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
I am trying to understand LockSupport.java and referred to its documentation. In there, it has code snippet, in which the authors have provided a sample of implementing a Mutex using LockSupport#park() and LockSupport#Unpark().
I used that sample and created a program that uses that sample FIFOMutex.
FIFOMutex code (taken from LockSupport.java)
package com.example.java.locking.studies.locksupport.from.javadoc;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;
class FIFOMutex {
private final AtomicBoolean locked = new AtomicBoolean(false);
private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
public void lock() {
boolean wasInterrupted = false;
Thread current = Thread.currentThread();
waiters.add(current);
// Block while not first in queue or cannot acquire lock
while (waiters.peek() != current ||
!locked.compareAndSet(false, true)) {
LockSupport.park(this);
if (Thread.interrupted()) // ignore interrupts while waiting
wasInterrupted = true;
}
waiters.remove();
if (wasInterrupted) // reassert interrupt status on exit
current.interrupt();
}
public void unlock() {
locked.set(false);
LockSupport.unpark(waiters.peek());
}
}
Now, I wrote the below program to use FIFOMutex as locking mechanism, code below:
package com.example.java.locking.studies.locksupport.from.javadoc;
public class FIFOMutexMainApp {
public static void main(String[] args) throws InterruptedException {
FIFOMutex mutex = new FIFOMutex();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Inside thread -> " + Thread.currentThread() + "Before mutex.lock()");
mutex.lock();
System.out.println("Inside thread -> " + Thread.currentThread() + "After mutex.lock()");
for (;;) {
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Inside thread -> " + Thread.currentThread() + "Before mutex.lock()");
mutex.unlock();
System.out.println("Inside thread -> " + Thread.currentThread() + "After mutex.lock()");
for (;;) {
}
}
});
t1.start();
Thread.sleep(10);
t2.start();
Thread.sleep(100);
mutex.lock();
System.out.println("Inside thread -> " + Thread.currentThread() + "will I get printed?");
}
}
Below is the output of this program:
Inside thread -> Thread[Thread-0,5,main]Before mutex.lock()
Inside thread -> Thread[Thread-0,5,main]After mutex.lock()
Inside thread -> Thread[Thread-1,5,main]Before mutex.lock()
Inside thread -> Thread[Thread-1,5,main]After mutex.lock()
Inside thread -> Thread[main,5,main]will I get printed?
Thread-1 starts and acquires the lock, followed by Thread-2, which invokes unlock(). Main calls lock(). My understanding was that Main will be blocked forever, even though Thread-2 invoked unlock(), as Thread-2 didn't ever invoke lock() (so that way, it was never granted a permit).
I am not able to understand this behavior. If I comment unlock() in Thread-2, then main-thread gets blocked forever.
How is it possible that a thread (in my case Thread-2) calls unlock() (which hasn't previously called lock()) and other thread (in this case main thread) calls lock(), but never gets locked?
If you dig into the source code, the unblock method actually release the CAS lock provided by variable locked and unpark the first thread. So if you comment out the invoking of unlock(), the CAS lock is not released and the main thread can stay in the while loop forever, which blocks the main thread.
First: the FIFOMutex invokes the
Thread current = Thread.currentThread();
Meaning the actual thread is taken for validation. That means the most actual thread is considered and that is:
Thread 1 at first and it issues the lock, then
Thread 2 is invoked and it issues the unlock.
and that is the reason why the main thread won't hang.
BUT: if you comment the unlock of thread 2 none is done and the main thread hangs. That is very understandable, isn't it?
I'm currently studying about signaling in threads and came across this article for signaling via shared objects,
http://tutorials.jenkov.com/java-concurrency/thread-signaling.html
It says that we can create a shared object and pass that object to threads which, threads can use to signal each other.
Following is the snippet provided for shared object,
public class MySignal{
protected boolean hasDataToProcess = false;
public synchronized boolean hasDataToProcess(){
return this.hasDataToProcess;
}
public synchronized void setHasDataToProcess(boolean hasData){
this.hasDataToProcess = hasData;
}
}
I tried to use it in my class as,
class MySignal {
boolean hasDataToProcess = false;
public MySignal(boolean defaultValue) {
this.hasDataToProcess = defaultValue;
}
public synchronized boolean hasDataToProcess() {
return this.hasDataToProcess;
}
public synchronized void setHasDataToProcess(boolean hasDataToProcess) {
this.hasDataToProcess = hasDataToProcess;
}
}
class MyThreadRunnable implements Runnable {
MySignal sharedSignal;
MyThreadRunnable(MySignal signal) {
this.sharedSignal = signal;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + " starts running..");
synchronized (sharedSignal) {
System.out.println(Thread.currentThread().getName() + " accessing sharedSignal");
while(sharedSignal.hasDataToProcess()) {
sharedSignal.setHasDataToProcess(false);
try {
System.out.println(Thread.currentThread().getName() + " going to sleep");
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
sharedSignal.setHasDataToProcess(true);
System.out.println(Thread.currentThread().getName() + " ended.");
}
}
}
public class Test2 {
public static void main(String[] args) {
MySignal mySignal = new MySignal(true);
MyThreadRunnable t1 = new MyThreadRunnable(mySignal);
MyThreadRunnable t2 = new MyThreadRunnable(mySignal);
Thread t3 = new Thread(t1);
Thread t4 = new Thread(t2);
t3.start();
t4.start();
}
}
This provided the expected output as,
Thread-1 starts running..
Thread-0 starts running..
Thread-1 accessing sharedSignal
Thread-1 going to sleep
Thread-1 ended.
Thread-0 accessing sharedSignal
Thread-0 going to sleep
Thread-0 ended.
But even if I remove the synchronized on the MySignal methods, this provides the same output as sharedSignal object is locked by one of the threads.
And, if I remove only the synchronized in run(), it does not work properly as one of the threads end before even going to sleep.
So this code is only running correctly due to the lock on sharedSignal object.
Is this how the signaling has to be used?
My intuition says that I've missed something. I tried searching for a good example but no luck so far. Any help would be appreciated.
But even if I remove the synchronized on the MySignal methods, this
provides the same output as sharedSignal object is locked by one of
the threads
Removing the synchronized from the methods won't make a difference as there is already a synchronized block guarding the method access from different threads.
And, if I remove only the synchronized in run(), it does not work
properly as one of the threads end before even going to sleep.
But if you remove the the synchronized block then the contents of the block are not executed in an atomic way.
What I mean is without the synchronized block the any thread can call the sharedSignal.hasDataToProcess() get the lock on the MySignal object and then release it after it is done with the method then another thread is free to call the sharedSignal.setHasDataToProcess(false); as the lock on the MySignal instance was already released by the earlier thread when it was done with the method.
//Acquires lock for the entire block
synchronized (sharedSignal) {
System.out.println(Thread.currentThread().getName() + " accessing sharedSignal");
while(sharedSignal.hasDataToProcess()) {
sharedSignal.setHasDataToProcess(false);
try {
System.out.println(Thread.currentThread().getName() + " going to sleep");
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
sharedSignal.setHasDataToProcess(true);
System.out.println(Thread.currentThread().getName() + " ended.");
}
Now without the synchronized block, the code of the block is not executed in an atomic way:
System.out.println(Thread.currentThread().getName() + " accessing sharedSignal");
//say thread1 acquires lock here
while(sharedSignal.hasDataToProcess()) {
//thread1 releases lock here, thread2 can acquire lock on the same object
sharedSignal.setHasDataToProcess(false);
try {
System.out.println(Thread.currentThread().getName() + " going to sleep");
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
sharedSignal.setHasDataToProcess(true);
System.out.println(Thread.currentThread().getName() + " ended.");
}
I am getting an Illegal State exception for following code :
synchronized (this) {
try {
Thread.currentThread().wait();
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
What i could made is synchronized on "this" will capture Monitor on Object calling the method and since i am calling wait on Current Thread object and i really don't have lock on that i am getting t error. Please validate my theory.
You call wait on the current thread, call it on this.
this.wait();
but then you will never get a notifyAll , because no thread that enters the synchronized block
can ever reach the notofyAll method. They all will wait for it first.
I guess you want one Thread to wait for another Thread to do some work.
Here is a short example of how synchronization between threads can work
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Object monitor = new Object();
Thread t1 = new Thread(new R1(monitor));
Thread t2 = new Thread(new R2(monitor));
t1.start();
t2.start();
t2.join();
t1.join();
}
public static class R1 implements Runnable {
private Object monitor;
public R1(Object monitor) {
this.monitor = monitor;
}
public void run() {
System.out.println("R1 entered run");
synchronized (monitor) {
try {
monitor.wait();
System.out.println("R1 got monitor back");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class R2 implements Runnable {
private Object monitor;
public R2(Object monitor) {
this.monitor = monitor;
}
public void run() {
System.out.println("R2 entered run");
synchronized (monitor) {
System.out.println("R2 will sleep for 1 sec");
try {
Thread.sleep(1000);
System.out
.println("R2 will notify all threads waiting for monitor");
monitor.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Output is:
R1 entered run
R2 entered run
R2 will sleep for 1 sec
R2 will notify all threads waiting for monitor
R1 got monitor back
You have acquired the lock of
this(current object)
and you are calling `
wait()
` on current thread that is why.
you should acquire lock before calling wait, notify notifyAll
Case1
...
synchronized(this){
this.wait();
}
...
Case2
...
synchronized(this){
Thread.currentThread.wait();
}
...
Case 1 is sensible code. It waits until another thread calls notify[All]() on "this" object.
Case 2 looks silly. It could only execute if the current thread and "this" were the same object, or you already had a lock on the current thread. Otherwise, you'd get IllegalMonitorStateException. Synchronising on Thread objects is a Bad Thing, because you can't be sure what else might be synchronising on them.
By the way, if what you want to do is just pause for a while in the program, you should sleep(), not wait().
From the Java doc for Object class wait() method:
IllegalMonitorStateException - if the current thread is not the owner
of the object's monitor.
In your code, current thread is the owner of the monitor of this and wait is called on Thread.currentThread.
Replace Thread.currentThread().wait(); with this.wait();
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.