Code with notify and notifyAll / synchronization (Help to understand) - java

I'm studying for an exam from a Book given by my professor and there is this code working with Threads and Synchronization: We want to be notified everytime the state changes (without missing a state change).
public class C {
private int state = 0; // the state
private boolean modified = false; // to show if the state was changed since actualization
public synchronized void printNewState() {
while (true) {
if (!modified) {
wait();
}
System.out.println(state);
modified = false;
notify();
}
}
public synchronized void setValue(int v) {
if (modified) {
wait();
}
state = v;
notify();
modified = true;
System.out.println("value set");
}
}
And then it's writen:
However, it is not guaranteed that notify() in the method SetValue(int) wakes up the printNewState Thread! In Java we solve this problem
with the help of notifyAll() and take a little busy waiting:
public synchronized void printNewState() {
while (true) {
while (!modified) {
wait();
}
System.out.println(state);
modified = false;
**notify();** \\(?)
}
}
public synchronized void setValue(int v) {
while (modified) {
wait();
}
state = v;
notifyAll();
modified = true;
System.out.println("value set");
}
I don't understand why the notify wasn't also changed to notifyAll()? It might not be guaranteed that this notify goes to a Thread of setValue(int) ???
Thank you

The notify() method wakes up a single waiting thread, whereas the notifyAll() method wakes up all the waiting threads. The problem is that with notify(), the thread that is woken up is effectively random.
If some other thread is accidentally or maliciously wait()ing on the same object, it could receive the notification instead of the thread you expect to wake up.
Take a look at this answer for some more information. The comments on that answer are also quite interesting.
EDIT
In the code sample you posted, the first notify() within printNewState() can handle only one update at a time, so it doesn't make sense to notify all waiting threads to post their updates. The code assumes, however, that only threads invoking setValue(int) are waiting.
Since public synchronized void setValue(int) is essentially the same as having synchronized(this) as the first line of the method, that isn't actually guaranteed. Any code that has a reference to an instance of C class can wait on it and screw up the code.
The synchronization and wait/notify actions should happen on an object lock/monitor. private final Object monitor = new Object(), synchronized(this.monitor), this.monitor.wait(), this.monitor.notifyAll(), etc.
I would also like to note that modified = true needs to be placed before notifyAll() in setValue(int), otherwise other waiting update threads will proceed without printNewState() noticing the update.
Also, private boolean modified should really be private volatile boolean modified, and the same for private int state, though an AtomicInteger may be a better option.

Related

Java synchronization: synchronized, wait(), notify()

I am trying to understand inter-thread communication in Java, and read that the support comes by using: wait(), notify(), notifyAll() methods.
In order thread to execute any of these methods, the thread needs to be owner of object's lock for which thread is invoking (any of these) methods. In addition to this, all these methods needs to be in a synchronized block/method. So far good.
I tried to implement a program in which one thread prints odd numbers, and other thread prints even numbers.
The program works correctly, however, at the same time, it raised few more doubts.
Below is the complete source code of the program which I implemented.
PrintEvenNumThread.java // prints the even numbers
package com.example.multithr.implrun;
import com.example.common.ObjectToWaitOn;
public class PrintEvenNumThread implements Runnable {
private ObjectToWaitOn objectToWaitOn;
public PrintEvenNumThread(ObjectToWaitOn objectToWaitOn) {
this.objectToWaitOn = objectToWaitOn;
}
#Override
public void run() {
int numToPrint = 2;
for (;;) {
synchronized (objectToWaitOn) {
while(objectToWaitOn.getPrintEvenOrOdd() != 2) {
try {
objectToWaitOn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
objectToWaitOn.print("EvenThread",numToPrint);
numToPrint += 2; // Generate next even number
objectToWaitOn.setPrintEvenOrOdd(1);
objectToWaitOn.notifyAll();
}
}
}
}
PrintOddNumsThread.java // Prints the odd numbers
package com.example.multithr.implrun;
import com.example.common.ObjectToWaitOn;
public class PrintOddNumsThread implements Runnable {
private ObjectToWaitOn objectToWaitOn;
public PrintOddNumsThread(ObjectToWaitOn objectToWaitOn) {
this.objectToWaitOn = objectToWaitOn;
}
#Override
public void run() {
int numToPrint = 1;
for(;;) {
synchronized(objectToWaitOn) {
while(objectToWaitOn.getPrintEvenOrOdd() != 1) {
try {
objectToWaitOn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
objectToWaitOn.print("OddThread", numToPrint);
numToPrint += 2; // Generate next odd number
objectToWaitOn.setPrintEvenOrOdd(2);
objectToWaitOn.notifyAll();
}
}
}
}
ObjectToWaitOn.java // The "shared" object for inter-thread communication
package com.vipin.common;
public class ObjectToWaitOn {
private int printEvenOrOdd;
public ObjectToWaitOn(int printEvenOrOdd) {
this.printEvenOrOdd = printEvenOrOdd;
}
public int getPrintEvenOrOdd() {
return printEvenOrOdd;
}
public void setPrintEvenOrOdd(int printEvenOrOdd) {
this.printEvenOrOdd = printEvenOrOdd;
}
public void print(String byThread, int numToPrint) {
System.out.println(byThread + ": " +numToPrint);
}
}
PrintEvenOddNumsMainApp.java
package com.example.multithr.main.app1;
import com.example.common.ObjectToWaitOn;
import com.example.multithr.implrun.PrintEvenNumThread;
import com.example.multithr.implrun.PrintOddNumsThread;
public class PrintEvenOddNumsMainApp {
public static void main(String[] args) {
ObjectToWaitOn obj = new ObjectToWaitOn(1); // 1 == odd; 2 == even
PrintEvenNumThread printEvenNumThread = new PrintEvenNumThread(obj);
PrintOddNumsThread printOddNumsThread = new PrintOddNumsThread(obj);
Thread evenNum = new Thread(printEvenNumThread);
Thread oddNum = new Thread(printOddNumsThread);
evenNum.start();
oddNum.start();
}
}
My doubt is:
1) When any of these threads releases lock by calling notifyAll() on object objectToWaitOn (which is shared between these threads), does it release the lock immediately? I have this doubt because these threads are in synchronized block based on objectToWaitOn object; so even if a thread calls the notifyAll(), shouldn't it still hold the lock because it is in synchronized block?
2) When a thread is in waiting condition by calling wait() on objectToWaitOn, and if other thread released the lock by invoking notifyAll(), does the waiting thread waits for lock to release or something else? Doesn't a thread coming out of the synchronized block anyway release the lock on the object it holds; so in above example if a thread is holding lock on objectToWaitOn and comes out of the synchronized block, doesn't it anyway release the lock for objectToWaitOn, and shouldn't based on this the other thread wake up?
Can anyone help me clarify these doubts?
Does it release the lock immediately?
No, it doesn't. The thread continues executing next statements within the synchronisation block.
Shouldn't it still hold the lock because it is in a synchronized block?
Yes, it should. A thread that calls the notify/notifyAll methods must hold the lock and will continue holding it until it leaves the synchronisation block normally or an exception happens:
If execution of the Block completes normally, then the monitor is unlocked and the synchronized statement completes normally.
If execution of the Block completes abruptly for any reason, then the monitor is unlocked and the synchronized statement completes abruptly for the same reason.
JLS-14.19
The notify/notifyAll methods change the state of the threads1 that are waiting on this monitor from State.WAITING to State.RUNNABLE. When the threads are woken up, they can participate in acquiring the lock.
Coming up to the monitor, some of them2 might get the STATE.BLOCKED state and wait until the other thread releases the lock. Note that it doesn't require any notifications from the thread which holds the lock.
The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
docs
1. In case of notify, it's a single arbitrary chosen thread.
2. Or all of them - if the thread that notified keeps holding the monitor.

Waking up a thread without risking to get blocked

I have a worker thread running indefinitely, which goes to sleep for one minute if there's nothing to do. Sometimes, another piece of code produces some work and wants to wake the worker thread immediately.
So I did something like this (code for illustration only):
class Worker {
public void run() {
while (!shuttingDown()) {
step();
}
}
private synchronized void step() {
if (hasWork()) {
doIt();
} else {
wait(60_000);
}
}
public synchronized wakeMeUpInside() {
notify();
}
}
What I dislike is having to enter the monitor only for waking something up, which means that the notifying thread may be delayed for no good reason. As the choices of native synchronization are limited, I thought I'd switch to Condition, but it has exactly the same problem:
An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called.
Here's a semaphore based solution:
class Worker {
// If 0 there's no work available
private workAvailableSem = new Semaphore(0);
public void run() {
while (!shuttingDown()) {
step();
}
}
private synchronized void step() {
// Try to obtain a permit waiting up to 60 seconds to get one
boolean hasWork = workAvailableSem.tryAquire(1, TimeUnit.MINUTES);
if (hasWork) {
doIt();
}
}
public wakeMeUpInside() {
workAvailableSem.release(1);
}
}
I'm not 100% sure this meets your needs. A few things to note:
This will add one permit each time wakeMeUpInside is called. Thus if two threads wake up the Worker it will run doIt twice without blocking. You can extend the example to avoid that.
This waits 60 seconds for work to do. If none is available it'll end up back in the run method which will send it immediately back to the step method which will just wait again. I did this because I'm assuming you had some reason why you wanted to run every 60 seconds even if there's no work. If that's not the case just call aquire and you'll wait indefinitely for work.
As per comments below the OP wants to run only once. While you could call drainPermits in that case a cleaner solution is just to use a LockSupport like so:
class Worker {
// We need a reference to the thread to wake it
private Thread workerThread = null;
// Is there work available
AtomicBoolean workAvailable = new AtomicBoolean(false);
public void run() {
workerThread = Thread.currentThread();
while (!shuttingDown()) {
step();
}
}
private synchronized void step() {
// Wait until work is available or 60 seconds have passed
ThreadSupport.parkNanos(TimeUnit.MINUTES.toNanos(1));
if (workAvailable.getAndSet(false)) {
doIt();
}
}
public wakeMeUpInside() {
// NOTE: potential race here depending on desired semantics.
// For example, if doIt() will do all work we don't want to
// set workAvailable to true if the doIt loop is running.
// There are ways to work around this but the desired
// semantics need to be specified.
workAvailable.set(true);
ThreadSupport.unpark(workerThread);
}
}

Java wait() does not get waked by notify()

Hallo I've been debugging my code for a whole day already, but I just can't see where could be wrong.
I use SerialPortEventListener on a main thread, in a working thread I have a client socket communicating to a server.
Since after this working thread reach return, I still need some wrap up work done in the main thread, i want to create a "pseudothread" that wait in the main thread until the it is notified from the listener onEvent method.
but this pseudothread seems to be waiting forever.
I checked the locked thread pseudoThread, they should have the same object id in the Runnable and in Listener class.
"PseudoThread waiting" got displayed, but PseudoThread awake is never showed.
Console output shows:
PseudoThread waiting
..
..
false notified pseudothread.
PS if I create a lock in Main class with public final Object lock = new Object(); and replace all main.pseudoThread with main.lock, I get java.lang.IllegalMonitorStateException.
private class Pseudo implements Runnable{
Main main;
public Pseudo(Main main) {
this.main = main;
}
#Override
public void run() {
synchronized(main.pseudoThread){
try {
System.out.println("PseudoThread waiting");
main.pseudoThread.wait();
System.out.println("PseudoThread awake");
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
}
in main method:
public static void main(String[] args) {
Main main = new Main();
main.initArduino();
//more code. including starting the working thread
main.pseudoThread = new Thread(main.new Pseudo(main));
main.pseudoThread.start();
try {
main.pseudoThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void initArduino() {
arduino = new Arduino(this);
if(!arduino.initialize())
System.exit(1);
}
and in the listener class (which also runs in main thread)
//class constructor;
public Arduino(Main Main){
this.main = Main;
}
//listening method
public void serialEvent(SerialPortEvent oEvent){
//some code to interract with working thread.
record();
}
private void record(){
synchronized(main.pseudoThread){
main.pseudoThread.notify();
System.out.println("notified pseudothread.");
}
}
Without looking too deeply into what might actually be happening, I can see that your use of wait()/notify() is all wrong. Probably you are experiencing a "lost notification." The notify() function does nothing if there is no thread waiting for it at the moment when it is called. If your serialEvent() function calls notify() before the other thread calls wait(), then the notification will be lost.
Consider this example:
class WaitNotify() {
private final Object lock = new Object();
private long head = 0;
private long tail = 0;
public void consumer() {
synchronized (lock) {
while(head == tail) {
lock.wait();
}
doSomething();
count head += 1;
}
}
public void producer() {
synchronized (lock) {
tail += 1;
lock.notify();
}
}
}
The essential points are:
(1) The consumer() function waits for some relationship between data to become true: Here, it waits for head != tail.
(2) The consumer() function waits in a loop. There's two reasons for that: (a) Many programs have more than one consumer thread. If consumer A wakes up from the wait(), there's no guarantee that consumer B hasn't already claimed whatever it was that they both were waiting for. And (b) The Java language spec allows foo.wait() to sometimes return even when foo.notify() has not been called. That's known as a "spurious wakeup." Allowing spurious wakeups (so long as they don't happen too often) makes it easier to implement a JVM.
(3) The lock object is the same lock that is used by the program to protect the variables upon which the condition depends. If this example was part of a larger program, you would see synchronized(lock) surrounding every use of head and tail regardless of whether the synchronized code is wait()ing or notify()ing.
If your own code obeys all three of the above rules when calling wait() and notify(), then your program will be far more likely to behave the way you expect it to behave.
As suggested by james it could be lost notification case or it could be that.. Two Threads 1- Your Main Thread and 2- Pseudo thread Are waiting on the same Thread Instance Lock (main.pseudoThread)( Main thread waits on the same lock by calling join method).
Now you are using notify which wakes the Main thread from join method and not the one
waiting in your Pseudo. To check for the second case try calling notifyall in record this will either
confirm the second case or will rule this possibility.
Anyways please refactor your code not to use synch on Thread instance its bad practice. Go for ReentrantLock or CoundDownLatch something.
Usage of notify and wait seem to be incorrect. Method name notify can be a bit misleading because it is not for general purpose "notifying". These methods are used to control the execution of synchronization blocks. Wait will allow some other thread to synchronize with same object while current threads pauses. Basically this is used when some resource is not available and execution can not continue. On the other hand notify will wake one waiting thread wake from wait after notifying thread has completed its synchronized-block. Only one thread can be in synchronized block of the same object at the same time.
If the idea is just keep the main program running until notified then semaphore would be much more appropriate. Something like this.
public void run() {
System.out.println("PseudoThread waiting");
main.semaphore.acquireUninterruptibly();
System.out.println("PseudoThread awake");
}
//...
private void record(){
main.semaphore.release();
}
//...
public static void main(String[] args) {
main.semaphore = new Semaphore(0);
//...
}

Java - Call wait() on an object and then allow object access to method

I have this method which takes a thread as a parameter. I want this method to be able to make a thread wait if there is not one waiting already and then wake up when another thread comes into the method so that the two of them can interact. I think I'm close but after I call wait() on the first thread no other threads can gain access to that method. Here is a minimalist version of my code:
// In the class 'Node'
public synchronized void trade(Thread thread)
{
if (!threadWaiting)
{
threadWaiting = true;
synchronized(thread)
{
try {
thread.wait();
} catch (InterruptedException e) {...}
}
}
}
I apologise for missing anything obvious, I've been looking around for an answer but I'm new to threading so I've no idea what to look for.
So my problem is that when another thread attempts to get into trade() they can't, the debugger just stops right there.
EDIT:
Here's some more clarification on what I'm asking. I'm afraid I wasn't too clear in my original post.
So I have one class called Node and another class called Bot. Bot extends thread so that it can be paused. At the start of the program multiple Bot objects are created and are then started, each Bot will then call the trade() method of the Node and pass itself to the method. If a Bot is the first in the method then I want its thread to wait on the Node until another Bot comes along (The waiting Bot will be stored in the Node), at which point the two Bots will interact.
Below is a clearer example of my method in pseudo code:
// Variable to hold the bot that is waiting.
private Bot waitingBot = null;
// Method belonging to Node.
public synchronized void trade(Bot currentBot)
{
if (waitingBot == null)
{
waitingBot = currentBot;
waitingBot.wait();
}
else
{
currentBot.interactWith(waitingBot);
waitingBot.notify();
waitingBot = null;
}
}
Sorry about the wording of my original post.
Your implementation has a flaw. You are taking lock on parameter passed which will be different for all Threads so they can't interact with wait notify.
EDIT: I am not sure what exactly your aim is but based on details this might help:
EDIT2: Added lock()
private final Lock lck = new ReentrantLock();
private final Condition cnd = lck.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
public synchronized void trade(Thread thread)
{
lck.lock();
try{
if(threadwaiting.get()){
cnd.signalAll();
threadwaiting.set(false);
//perform your task
}else{
cnd.await();
threadwaiting.set(true);
}
}
} finally {
lck.unlock()
}
}
EDIT:
Looking at your updated post , you should use cyclicbarrier with count 2 then that should solve it all for you.
This is a dead lock, because when you call thread.wait(); you release thread object lock. But this object lock on synchronized method remains, that's why no one else can enter it.
It's like loki's code, but improved
private final Lock lock = new ReentrantLock();
private final Condition cnd = lock.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
public void trade(Thread thread) {
lock.lock();
if (threadwaiting.get()) {
cnd.signalAll();
lock.unlock();
// perform your task of second thread
} else {
threadwaiting.set(true);
try {
cnd.await();
// perform your task of first thread
} catch (InterruptedException e) {
} finally {
threadwaiting.set(false);
lock.unlock();
}
}
}

Is notifyAll() required at the end of a synchronized block?

I used to write a synchronized block like:
synchronized(foobar) {
// do something
}
But, recently I saw someone write:
synchronized(foobar) {
// do something
foobar.notifyAll();
}
Is foobar.notifyAll(); necessary? What happens if I omit it?
The short answer is that is depends on what you are doing.
If the goal of the synchronized block is simply to ensure that access / updates to a data structure are performed safely, then notify() or notifyAll() serves no purpose.
On the other hand, if the goal is to implement a "condition variable" then the notify() or notifyAll() calls work with a wait call like this ... for example:
private boolean flag;
private final Object mutex = new Object();
public void awaitFlag(boolean flag) {
synchronized (mutex) {
while (this.flag != flag) {
mutex.wait();
}
}
}
public void setFlag(boolean flag) {
synchronized (mutex) {
this.flag = flag;
mutex.notifyAll();
}
}
The above implements a simple mechanism where threads call awaitFlag() to wait for the flag to become true or false. When another thread calls setFlag() to change the flag, all of the threads that are currently waiting for the flag to change will get woken up by the notifyAll(). This is an example where the notifyAll() is essential to the working of the code.
So to understand whether the notify or notifyAll code is necessary, you need to figure out if some other code might call wait on the same mutex / lock object.
You don't need to do this. You only have to do it if the object (here foobar) is waiting to be notified. Notify only Wakes up all threads that are waiting on this object's monitor.
In Java, you can use wait(), notify() and notifyAll() to achieve thread co-ordination. See How to use wait and notify in Java?
The notifyAll() is to tell any other thread sleeping in a foobar.wait() that the current thread is about to release the lock and they can compete for the resource again.

Categories