System.out.println Line Affecting Execution of the Logic - java

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).

Related

Do while loops stop executing after a while? [duplicate]

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.

While-loop stops checking if-statement? [duplicate]

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.

Non volatile status flag in multi-threaded code

I am a novice when it comes to concurrency and unsure of myself when spotting issues, I was looking through a fairly established code base and found the following code (edited for brevity) which I believe to be susceptible to data races:
public class Example extends Thread {
boolean condition = false;
public void run () {
while (true) {
synchronized (this) {
try {
while( condition ) wait();
}
catch (InterruptedException e) { /*for brevity*/ }
}
// non-blocking computation
}
}
public void setTrue () { condition = true; }
public void setFalse () {
synchronized (this) {
condition = false;
this.notifyAll();
}
}
}
As far as I understand condition must be volatile since even with the synchronized block, the compiler will not issue any memory barriers; if it were a volatile store to condition in setTrue the compiler would issue StoreEnter.
Am I right to believe the above is susceptible to data races? And if so how can I witness the data race through an example (as opposed to simply knowing the guarantees provided by the JMM). A simple test with threads randomly invoking setTrue in a loop doesn't uncover the data race.
Also, I believe the use of notifyAll is overkill here since there is one condition to check and only one thread will ever be waiting on it, right?
Thank you.
As far as I understand condition must be volatile since even with the synchronized block, the compiler will not issue any memory barriers; if it were a volatile store to condition in setTrue the compiler would issue StoreEnter.
That is not correct. When you use a shared variable within a synchronized block, your code will be thread-safe with respect to other threads using the same variable with the same lock. If memory barriers are required, then they will be used.
However, the code you have shown us is is incorrect because the setTrue() method is updating the flag outside of a synchronized block.
Am I right to believe the above is susceptible to data races?
Yea ... sort of. The scenario is as follows:
The condition is false.
Some other thread calls setTrue which sets the condition variable to true in its cache. But since the setTrue method doesn't use synchronized, there is no write barrier, and no flushing to main memory.
The "example" thread fetches the latest committed value from main memory (which is still false), and doesn't wait as it is supposed to do.
Also, I believe the use of notifyAll is overkill here since there is one condition to check and only one thread will ever be waiting on it, right?
It could be replaced with a notify() ... if that is what you mean. But to be honest, it makes no real difference which flavour of notify you use.
You commented:
I meant that the compiler would not consider it necessary to submit a memory barrier in this situation.
Maybe. But the "monitorenter" and "monitorexit" instructions implicitly involve memory barriers.
And:
Wouldn't it also be correct if condition were volatile?
If you are talking about using volatile AND synchronized, then yes it would be correct ... though the volatile would be redundant (assuming that the setTrue bug is fixed.)
If you are talking about volatile only, then no. You can't implement an efficient "wait on a condition variable" with just volatile. The problem is that neither the "read/test/wait" or "write/notify" sequences can be performed atomically; i.e. without the possibility of race-conditions.
And besides, you can't do the equivalent of wait/notify without using a primitive object mutex, or a Lock object.
Am I right to believe the above is susceptible to data races?
Don't think so. condition is unimportant, it only permits the method to avoid waiting. The way it is set is also not important. It doesn't need to be volatile, as it's use is local to one object.
Also, I believe the use of notifyAll is overkill here since there is
one condition to check and only one thread will ever be waiting on it,
right?
NotifyAll is fine, while there is only one thread waiting in the method there may be many other threads waiting on, or waiting for, the thread.

Questions on Concurrency from Java Guide

So I've been reading on concurrency and have some questions on the way (guide I followed - though I'm not sure if its the best source):
Processes vs. Threads: Is the difference basically that a process is the program as a whole while a thread can be a (small) part of a program?
I am not exactly sure why there is a interrupted() method and a InterruptedException. Why should the interrupted() method even be used? It just seems to me that Java just adds an extra layer of indirection.
For synchronization (and specifically about the one in that link), how does adding the synchronize keyword even fix the problem? I mean, if Thread A gives back its incremented c and Thread B gives back the decremented c and store it to some other variable, I am not exactly sure how the problem is solved. I mean this may be answering my own question, but is it supposed to be assumed that after one of the threads return an answer, terminate? And if that is the case, why would adding synchronize make a difference?
I read (from some random PDF) that if you have two Threads start() subsequently, you cannot guarantee that the first thread will occur before the second thread. How would you guarantee it, though?
In synchronization statements, I am not completely sure whats the point of adding synchronized within the method. What is wrong with leaving it out? Is it because one expects both to mutate separately, but to be obtained together? Why not just have the two non-synchronized?
Is volatile just a keyword for variables and is synonymous with synchronized?
In the deadlock problem, how does synchronize even help the situation? What makes this situation different from starting two threads that change a variable?
Moreover, where is the "wait"/lock for the other person to bowBack? I would have thought that bow() was blocked, not bowBack().
I'll stop here because I think if I went any further without these questions answered, I will not be able to understand the later lessons.
Answers:
Yes, a process is an operating system process that has an address space, a thread is a unit of execution, and there can be multiple units of execution in a process.
The interrupt() method and InterruptedException are generally used to wake up threads that are waiting to either have them do something or terminate.
Synchronizing is a form of mutual exclusion or locking, something very standard and required in computer programming. Google these terms and read up on that and you will have your answer.
True, this cannot be guaranteed, you would have to have some mechanism, involving synchronization that the threads used to make sure they ran in the desired order. This would be specific to the code in the threads.
See answer to #3
Volatile is a way to make sure that a particular variable can be properly shared between different threads. It is necessary on multi-processor machines (which almost everyone has these days) to make sure the value of the variable is consistent between the processors. It is effectively a way to synchronize a single value.
Read about deadlocking in more general terms to understand this. Once you first understand mutual exclusion and locking you will be able to understand how deadlocks can happen.
I have not read the materials that you read, so I don't understand this one. Sorry.
I find that the examples used to explain synchronization and volatility are contrived and difficult to understand the purpose of. Here are my preferred examples:
Synchronized:
private Value value;
public void setValue(Value v) {
value = v;
}
public void doSomething() {
if(value != null) {
doFirstThing();
int val = value.getInt(); // Will throw NullPointerException if another
// thread calls setValue(null);
doSecondThing(val);
}
}
The above code is perfectly correct if run in a single-threaded environment. However with even 2 threads there is the possibility that value will be changed in between the check and when it is used. This is because the method doSomething() is not atomic.
To address this, use synchronization:
private Value value;
private Object lock = new Object();
public void setValue(Value v) {
synchronized(lock) {
value = v;
}
}
public void doSomething() {
synchronized(lock) { // Prevents setValue being called by another thread.
if(value != null) {
doFirstThing();
int val = value.getInt(); // Cannot throw NullPointerException.
doSecondThing(val);
}
}
}
Volatile:
private boolean running = true;
// Called by Thread 1.
public void run() {
while(running) {
doSomething();
}
}
// Called by Thread 2.
public void stop() {
running = false;
}
To explain this requires knowledge of the Java Memory Model. It is worth reading about in depth, but the short version for this example is that Threads have their own copies of variables which are only sync'd to main memory on a synchronized block and when a volatile variable is reached. The Java compiler (specifically the JIT) is allowed to optimise the code into this:
public void run() {
while(true) { // Will never end
doSomething();
}
}
To prevent this optimisation you can set a variable to be volatile, which forces the thread to access main memory every time it reads the variable. Note that this is unnecessary if you are using synchronized statements as both keywords cause a sync to main memory.
I haven't addressed your questions directly as Francis did so. I hope these examples can give you an idea of the concepts in a better way than the examples you saw in the Oracle tutorial.

Infinite loop problem with while loop and threading [duplicate]

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.

Categories

Resources