This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 5 years ago.
I have a short while loop like:
boolean a = false;
MyClass b = new MyClass();
b.b = false;
// b is used in other thread...
while(!a){
if(b.b){
throw new Exception("b is true");
}
}
In this case a will never became true, but after some runs the boolean variable b.b should became true. Strangely the while-loop was never left and my programm endet in an endless loop.
I woundered why and decided to add a System.out.print statement to the loop:
while(!a){
if(b.b){
throw new Exception("b is true");
}
System.out.println("there is something more to execute");
}
Remarkably my code works like it should be. The while loop runs over the if statement until b.b is true and the throwing of the exception leaves the loop.
Could it be that in the first case the program stops checking the if statement because the compiler thinks that it is not necessary to check again? If not, could anybody explain to me, why the first case does not work but the second one does?
You need to mark your variables (whichever have got access to multiple threads) as volatile if you are working in a multithreaded environment, otherwise, it is not guaranteed for the current thread to see the results written by another thread.
In other words, one thread writes (changes) the value of your variable a and the other thread is not guaranteed to see it (because threads might copy/cache the variables), which is causing your while loop not to break.
I suggest you look here and understand how volatile works in a multithreaded environment. Below text (emphasis mine) taken from the same link:
Changes to a volatile variable are always visible to other threads. When a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
Related
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 4 years ago.
So Im experimenting a bit with multithreading currently, since im still pretty new to Java. Now, I have multiple threads that all influence the same long variable. However, it seems that afer a while of not doing anything but checking the if statement the while loop just stops executing (as in, it loops infinitely). It does work if i just print something within the while-loop.
Does not work:
while(true){
if(longVariable < 2)
break;
}
Does somehow work:
while(true){
System.out.println("hi");
if(longVariable < 2)
break;
}
Why is this?
while(true){
if(longVariable < 2)
break;
}
In this code, there is no reason for the JVM to believe that longVariable will ever change. It can effectively rewrite it to:
long cached = longVariable;
while(true){
if(cached < 2)
break;
}
Which loops infinitely if longVariable is at least two when it executes, because nothing can change cached.
You have to give the compiler a hint that this rewrite isn't allowed. It works with the System.out.println on your JVM because it happens to be implemented with synchronization (which is common, but not required). This inserts memory barriers which means that the cached value of longVariable is invalidated, and has to be read again.
But it's not guaranteed to work. To make it work correctly, either declare the variable volatile:
volatile long longVariable
which prevents its value from being cached.
Or use something like an AtomicLong instead of a plain long variable.
Or, most onerously, use explicit synchronization (ensuring that all reads of and writes to the variable are synchronized on the same "something"):
long v;
synchronized (something) {
v = longVariable;
}
if (v < 2) ...
When you have a non volatile variable which is not updated by a thread, it is free to inline it.
In your first case, once the code has compiled by the JIT, it might no longer read the value and instead make the condition always true.
In the second case, you have a thread safe operation. println on System.out is a synchronized method. This adds a read and write barrier and prevents the JIT from optimising the read operation away.
If you try this, it should also work.
while(true){
synchronized("hi") { } // does nothing but add memory barriers.
if(longVariable < 2)
break;
}
It also slows down the code by more than 1000x so the method might not have been JITed by the time you try to stop the thread.
The simple solution is to make the variable volatile and it will be read in a thread safe manner every time.
I have run into an incredibly strange phenomenon. I am currently programming an instant messenger program in Java and I have a variable to represent whether a new user has connected (this is of in a separate class). Here is the code in question where the object ListenerThread extends Thread :
boolean listenerThreadConnected = ServerDriver.getListenerThread().connected;
System.out.println("Whatever in here");
if(listenerThreadConnected){
...
System.out.println("In the if statement");
...
}
So, this code works. When listenerThreadConnected = true the if statement executes and it outputs In the if statement and does all of the other stuff in the if statement. However, I changed no other code other than commenting out the System.out.println("Whatever in here") and the if statement didn't trigger and there was no sign of the In the if statement being outputted. My code looked like this:
boolean listenerThreadConnected = ServerDriver.getListenerThread().connected;
//System.out.println("Whatever in here");
if(listenerThreadConnected){
...
System.out.println("In the if statement");
...
}
I am quite perplexed. How could this System.out.println affect the actual logic? I know this question is very open-ended, but have you ever had a similar experience? For some context, this is all in a while loop and ListenerThread is a concurrently running Thread. I can't seem to replicate this result except in my current code.
[EDIT] Replacing the System.out.println with a Thread.sleep(1) also seems to work, so this leads me to think that it is a concurrency issue.
Not so extrange at all, you are for sure in a multi thread system and your app is getting an outdated boolean value, you need to ensure memory visibility when reading the variable listenerThreadConnected
How:?
Declare this boolean listenerThreadConnected as volatile and the error must be gone!
Note that System.out.println is often implemented as synchronized (even though this isn't documented), in order that you don't get the output of two threads interleaving.
Executing that statement has the effect of making updates to variables visible to the thread in which the synchronized method is executed (it is a "happens before" relationship).
By removing the System.out.println call, you remove this behaviour, so you may see outdated variables.
As #Xoce웃Пepeúpa says, make the variable volatile, or do something else to ensure memory visibility (e.g. changing it to an AtomicBoolean).
This question already has answers here:
Why must wait() always be in synchronized block
(10 answers)
Closed 9 years ago.
In the book I'm reading it says:
This technique is needed due to a race condition that would otherwise
exist between setting and sending the notification and testing and
getting the notification. If the wait() and notify() mechanism were
not invoked while holding the synchronization lock, there would be no
way to guarantee that the notification would be received.
Don't understand what this exactly means, why can the race condition happen?
EDIT: Hmmmm, I see now that this is possibly a duplicate question of Why must wait() always be in synchronized block
, but it seams that the answers focus on making the condition check and going to wait synchronized.
Counterexample from shrini1000:
I can still do something like:
while(!condition) { synchronized(this) { wait(); } }
which means there's still a race between checking the condition and waiting even
if wait() is correctly called in a synchronized block. So is there
any other reason behind this restriction, perhaps due to the way it's
implemented in Java?
It must be all about the technique author must have presented before the article you have copied in question. I am not sure which book you are reading but I will try to answer this question.
I read a similar book "Thinking in Java" that talked about the same race condition. It suggests that this can be prevented using wait and notify so that the code doesn't miss the notify signal.
When two threads are coordinated using notify( )/wait( ) or notifyAll(
)/wait( ), it’s possible to miss a signal. Suppose T1 is a thread that
notifies T2, and that the two threads are implemented using the
following (flawed) approach:
T1:
synchronized(sharedMonitor) {
<setup condition for T2>
sharedMonitor.notify();
}
T2:
while(someCondition) {
// Assume that T2 evaluates someCondition and finds
// it true, now when program goes to next line thread
// scheduler switches to T1 and executes notify again
// after when control comes to T2 it blindly executes
// wait(), but it has already missed notify so it will
// always be waiting.
.... some code ....
synchronized(sharedMonitor) {
sharedMonitor.wait();
}
}
The (setup condition for T2) is an action to prevent T2 from calling wait( ), if it hasn’t already.
The solution is to prevent the race condition over the someCondition variable. Here is the correct approach for T2:
synchronized(sharedMonitor) {
while(someCondition) {
sharedMonitor.wait();
}
}
The fact that something can be misused is hardly a counterexample.
Java only enforces that wait() and notify() are part of a synchronized block (since that's the only way they are supposed to be used), but it's up to you to define the block boundaries.
As a counter-counterexample, think about the finally block. Java only enforces that it comes after a try block, but you're the only one who should know what's supposed to go into that try block; you could even leave it empty (which would then miss the very point of finally).
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I'm getting a very strange error. I have the following code:
while (true) {
System.out.println(model.getLightState());
if (model.getLightState() == 1) {
System.out.println("Entered..");
view.driveThroughJunction();
break;
}
}
Now, my program enters the if statement when the light state changes to '1' and executes the code that's fine. But this ONLY works if I have that print out statement after the while loop is entered. I find that weird. Will a 'sysout' line have any effect on the if statement? Apparently it does for the above case.
Any ideas to why this is ?
EDIT:
(in the model class)
public final byte getLightState() {
return lightChanger.getLightValue();
}
(in lightchanger class)
public byte getLightValue() {
return light.getState();
}
(in the light class)
public final byte getState() {
return this.state;
}
You have a synchronization problem, leading to a visibility problem. If no synchronization is used when reading and writing a variable shared by multiple threads, there is no guarantee that the value written by one thread is visible to other threads.
To fix that you need to do one of those things:
make the state field volatile
change the state field type to AtomicInteger
synchronize every access to the state field (using the synchronized keyword), using the same lock every time, of course.
Your sysout call makes the value visible because it internally calls some method that flushes the state of the registers to the main memory (by writing to a volatile field or calling a synchronized method, for example).
You should declare your model instance as volatile.
Volatile keyword in Java is used as an indicator to Java compiler and Thread that do not cache value of this variable and always read it from main memory. So if you want to share any variable in which read and write operation is atomic by implementation you should declare them as volatile variable.
Read more: http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2DFw4l8AW
From your comments it is apparent that more than one thread is accessing the same instance of model and performing read/write in the same instance of model. Without volatile threads do cache the value of model instance and hence end up in dirty reads. With System.out.println happening your read/write operation is delayed by a bit (due to output writing) hence thread is able to refresh the cached value from main memory.
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 8 years ago.
Using a basic example to illustrate my problem I have 2 near-identical bits of code.
This code causes the while loop to run infinitely.
private boolean loadAsset() {
new Thread(new Runnable() {
#Override
public void run() {
// Do something
loaded = true;
}
}).start();
while (!loaded) {
// System.out.println("Not Loaded");
}
System.out.println("Loaded");
return false;
}
This code however (i.e. doing something in the while loop) causes the loaded variable to be successfully evaluated and allows the while loop to break and method to finish.
private boolean loadAsset() {
new Thread(new Runnable() {
#Override
public void run() {
// Do something
loaded = true;
}
}).start();
while (!loaded) {
System.out.println("Not Loaded");
}
System.out.println("Loaded");
return false;
}
Can anyone explain to me why this is?
The first loop only "appears" to run infinitely. You're actually running an "active wait", burning 100% of your CPU, such that your OS or JVM can't make a context switch and let the other thread run.
With the System.out.println() on the other hand, there is I/O involved, resulting in a somewhat "inactive wait". The OS or JVM can switch contexts and the other thread starts.
If you'd run your first program for 10 hours, I'm sure the loop would break eventually
Check that 'loaded' is definitely declared as volatile.
Explanation: if a variable is read and/or written by multiple threads, then you need to take appropriate thread-safety measures. One such thread-safety measure is volatile, which is suitable for primitive values (or object references) which are read or written as 'simple' actions with the value written on a given occasion not depending on the previously read value. For more information, I have an article about volatile on my web site (along with other information about thread-safety generally) that may be of help.
If loaded is not volatile, the JIT is free to optimise it by placing it in a register and not loading it from memory every time. In the second case, the loop is too complex for the JIT to assume it doesn't need to load loaded each time.
Note: its is the JIT not the javac compiler which optimises the code.
Read up on Memory Consistency Errors. Basically, different threads have inconsistent views of what should be the same data. In order to resolve this, read up on Synchronization. Or simply declare loaded as volatile, since its value is only being written by a single thread.
I believe you are experiencing a Busy Wait with the empty loop, which will never sleep. Thus, your Thread to set loaded to true never runs.