About java volatile array - java

I have a problem about volatile arrays. On the internet most people say that the elements of an array are not guaranteed to be volatile, only its reference is. So I write some code to check for it. The result is, it turns out, that it works.
I'm using Windows 10 + JDK 8
My code:
static volatile boolean[] keepRunnin g= { true };
public static void main(String[] args) throws Exception {
new Thread(
()->{
while (keepRunning[0]){}
}
).start();
Thread.sleep(1000);
keepRunning[0] = false;
}
The loop always ends, it's not an infinite loop.
Can anyone explain it?

It is impossible to write code to prove that the elements in the array will always be visible to all threads when they should be.
Your example may demonstrate that it circumstantially works for you (I haven't run it) but you cannot be certain that it will work on all hardware, for all users, all of the time.
It is only possible to write code which disproves that something has visibility across threads. It is impossible to write code which proves it.

Related

Program not terminating after loop completion

In the following scenario, the boolean 'done' gets set to true which should end the program. Instead the program just keeps going on even though the while(!done) is no longer a valid scenario thus it should have halted. Now if I were to add in a Thread sleep even with zero sleep time, the program terminates as expected. Why is that?
public class Sample {
private static boolean done;
public static void main(String[] args) throws InterruptedException {
done = false;
new Thread(() -> {
System.out.println("Running...");
int count = 0;
while (!done) {
count++;
try {
Thread.sleep(0); // program only ends if I add this line.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(2000);
done = true; // this is set to true after 2 seconds so program should end.
System.out.println("Done!"); // this gets printed after 2 seconds
}
}
EDIT: I am looking to understand why the above needs Thread.sleep(0) to terminate. I do not want to use volatile keyword unless it is an absolute must and I do understand that would work by exposing my value to all threads which is not my intention to expose.
Each thread have a different cached version of done created for performance, your counter thread is too busy making the calculations for count that it doesnt give a chance to reload done.
volatile ensures that any read/write is done on the main memory, always update the cpu cache copy.
Thread.sleep always pause the current thread, so even if 0 your counter thread is interrupted by some time <1ms, that is enough time for the thread to be adviced of done variable change.
I am no Java expert man, I don't even program in java, but let me try.
A thread on stackoverflow explains the Java Memory model: Are static variables shared between threads?
Important part: https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
Chapter 17 of the Java Language Specification defines the
happens-before relation on memory operations such as reads and writes
of shared variables. The results of a write by one thread are
guaranteed to be visible to a read by another thread only if the write
operation happens-before the read operation. The synchronized and
volatile constructs, as well as the Thread.start() and Thread.join()
methods, can form happens-before relationships.
If you go through the thread, it mentions the "Happens before" logic when executing threads that share a variable. So my guess is when you call Thread.sleep(0), the main thread is able to set the done variable properly making sure that it "Happens first". Though, in a multi-threaded environment even that is not guaranteed. But since the code-piece is so small it makes it work in this case.
To sum it up, I just ran your program with a minor change to the variable "done" and the program worked as expected:
private static volatile boolean done;
Thank you. Maybe someone else can give you a better explanation :P

Why is this code not going into an infinite loop as suggested by JSR133?

In JSR-133 section 3.1, which discusses the visibility of actions between threads - it is mentioned that the code example below, which does not utilise the volatile keyword for the boolean field, can become an infinite loop if two threads are running it. Here is the code from the JSR:
class LoopMayNeverEnd {
boolean done = false;
void work() {
while (!done) {
// do work
}
}
void stopWork() {
done = true;
}
}
Here is a quote of the important bit in that section that I'm interested in:
... Now imagine that two threads are created, and that one
thread calls work(), and at some point, the other thread calls stopWork(). Because there is
no happens-before relationship between the two threads, the thread in the loop may never
see the update to done performed by the other thread ...
And here is my own Java code I wrote just so I can see it loop:
public class VolatileTest {
private boolean done = false;
public static void main(String[] args) {
VolatileTest volatileTest = new VolatileTest();
volatileTest.runTest();
}
private void runTest() {
Thread t1 = new Thread(() -> work());
Thread t2 = new Thread(() -> stopWork());
t1.start();
t2.start();
}
private void stopWork() {
done = true;
System.out.println("stopped work");
}
private void work() {
while(!done){
System.out.println("started work");
}
}
}
Although the results from consecutive executions are different - as expected - I don't see it ever going into an infinite loop. I'm trying to understand how I can simulate the infinite loop that the documentation suggests, what am I missing? How does declaring the boolean volatile, remove the infinite loop?
The actual behavior is OS and JVM specific. For example, by default, Java runs in client mode on 32-bit Windows and in server mode on the Mac. In client mode the work method will terminate, but will not terminate in server mode.
This happens because of the Java server JIT compiler optimization. The JIT compiler may optimize the while loop, because it does not see the variable done changing within the context of the thread. Another reason of the infinite loop might be because one thread may end up reading the value of the flag from its registers or cache instead of going to memory. As a result, it may never see the change made by the another thread to this flag.
Essentially by adding volatile you make the thread owning done flag to not cache this flag. Thus, the boolean value is stored in common memory and therefore guarantees visibility. Also, by using volatile you disabling JIT optimization that can inline the flag value.
Basically if you want to reproduce infinite loop - just run your program in server mode:
java -server VolatileTest
The default, non-volatile, implicit declaration of all Java values allows the Jit compiler to "hoist" references to non-volatile values, out of loops so that they are only read 'once'. This is allowed after a tracing of execution paths can safely arrive at the fact that the methods called inside of such a loop, don't ever cause entry back into the classes methods where it might mutate the value of these non-volatile values.
The System.out.println() invocation goes to native code which keeps the JIT from resolving that 'done' is never modified. Thus the hoist does not happen when the System.out.println() is there and as you found out, the infinite loop is only happening with it removed where the JIT can resolve that there is no write to 'done'.
The ultimate problem is that this reference hoisting is conditional on "reachability" of a mutation of the value. Thus, you may have moments where there is no reach to a mutation of the value, during development, and thus the hoist happens and suddenly you can't exit the loop. A later change to the loop might use some function that makes it impossible to discern that the value cannot be written by the logic in the loop, and the hoist disappears and the loop works again.
This hoist is a big problem for many people who don't see it coming. There is a pretty large group of belief now that safe Java has class level variables either declared as volatile or final. If you really need a variable to be "optimizable", then don't use a class level variable and instead make it a parameter, or copy it into a local variable for the optimizer to go after. Doing this with read only access helps manage "dynamic" changes in a value that disrupt predictable execution paths too.
There is has been recurring discussion on the java concurrency mailing list about this issue. They don't seem to believe that this is a problem for Java developers and that this "optimization" of reference is far more valuable to performance than problematic to development.

Why won't this 'if' statement run in a while loop without something else also happening in the while loop?

I'm having a problem where an if statement is only running if there is something else happening before it in the while loop.
Here is the code I want to use:
public void load() throws IOException, InterruptedException {
while (true) {
if (findGame == true) {
System.out.println(findGame);
}
}
}
That is simplified but it shows my problem. Basically, when findGame == true, the if statement does not run. The reason I don't think the if statement is running is because the variable is not being printed out to the console.
I did some tests and found that the if statement ran with the following code:
public void load() throws IOException, InterruptedException {
while (true) {
System.out.println("foo"); // New code added
if (findGame == true) {
System.out.println(findGame);
}
}
}
My question is why does it work with the above code but not the first one? The only difference between the two is that the one that works has something else added to the while loop.
If it makes a difference, the code I've shown above is running in a separate thread.
If it makes a difference, the code I've shown above is running in a separate thread.
And that's the problem. You're relying on a value set by one thread to be visible in another - and there's no such guarantee without memory barriers being involved. In your second code, the call to println is almost certainly responsible for creating the memory barriers required for the reading thread to "see" the value written by the writing thread. Memory models are hard, unfortunately :(
If you use AtomicBoolean instead of just a boolean field, you may well find the first code works instead - but even so, a tight loop is generally a bad idea. It would be better to use a semaphore or some similar kind of signalling, so the "reading" thread could just wait (idly) until there's a change. Look into java.util.concurrent for classes such as Semaphore and CountDownLatch. (You can do it with just wait and notify, but it'll be simpler if you use higher-level abstractions.)

How to trigger the reordering phenomenon in Java?

In a book called "Java Concurrency in Practice", I saw a sample code like this at the beginning of chapter 3
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}
The book says
"NoVisibility could loop forever because the value of ready might never become visible to the readerthread."
and
"NoVisibility could print zero because the write to ready might be made visible to the readerthread before the write to number, a phenomenon known as reordering."
I'd like to know how to trigger any one of the above events(i.e., loop forever or print zero).
Does anyone know how to make this happen?
I've tried executing this program on my machine(javaSE-1.7 on windows 8.1) for many times. It always print 42 as the result.
There's a lot of mysteries about multithreading, and you'll hurt your head trying to reason why things go wrong. Its easier to just do things right. That being said my elementary understanding is optimizations are made by the machine behind the scene that prevents threads from seeing the latest value posted by another thread. If you need an example just post some sleeping threads and have one change the value and another one read it later. Of the failure occurs there will be two different values for the supposed single value.

When Java refresh Thread Cache to actual copy

I read few articles on volatile Thread cache and found either it is too much brief without examples, so it is very difficult for beginner to understand.
Please help me in understanding below program,
public class Test {
int a = 0;
public static void main(String[] args) {
final Test t = new Test();
new Thread(new Runnable(){
public void run() {
try {
Thread.sleep(3000);
} catch (Exception e) {}
t.a = 10;
System.out.println("now t.a == 10");
}
}).start();
new Thread(new Runnable(){
public void run() {
while(t.a == 0) {}
System.out.println("Loop done: " + t.a);
}
}).start();
}
}
When I make a variable volatile and run my program then it stops after some time but when I remove volatile to a variable, then it goes on and my program is not stopping.
What I knew about volatile is "when variable is declared as volatile then thread will directly read/write to variable memory instead of read/write from local thread cache.
if not declared volatile then one can see delay in updation of actual value."
Also, as per my understanding of refreshing the cached copy, I thought program will stop in some time but then why in above program it is continuing to run and not updating.
So when is Thread referring to its local cache starts referring to main copy or refresh its value with main copy value?
Please correct me if I am wrong in my understanding....
Please explain me with some small code snippet or link.
when variable is declared as volatile then thread will directly read/write to variable memory instead of read/write from local thread cache. if not declared volatile then one can see delay in updation of actual value.
To begin with, the above statements are false. There are many more phenomena going on at the level of machine code which have nothing to do with any "thread-local variable caches". In fact, this concept is hardly applicable at all.
To give you something specific to focus on, the JIT compiler will be allowed to transform your code
while(t.a == 0) {}
into
if (t.a == 0) while (true) {}
whenever t.a is not volatile. The Java Memory Model allows any variable accessed in a data race to be treated as if the accessing thread was the only thread in existence. Since obviously this thread is not modifying t.a, its value can be considered a loop invariant and the check doesn't have to be repeated... ever.
This may or may not be necessarily what is happening, but volatile also prevents certain reordering by the compiler.
For instance your code here
while(t.a == 0) {}
System.out.println("Loop done: " + t.a);
Can be reordered to
if(t.a == 0){
while(true){
}
}
System.out.println("Loop done: " + t.a);
This is called hoisting and is perfectly legal. Declaring it volatile will prevent this sort of ordering.
If a variable is not declared volatile, whether it will be read from the cache or from the main copy is not predictable.
The cache has a limited size and the variable can get evicted from it for various reasons, like other variables occupying the cache. When this happens the main copy is read.
Marking a variable volatile is making sure changes to it are visible across threads.
In your code first thread changes the value of a and other thread sees this change and breaks out of loop.
Important point to note about volatile variable is value can change between last access and current access, even if compiler knows that its values is not being changed.
(as #Marko Topolnik said)
This stops the JIT compiler from doing optimizations like
while(t.a == 0) {}
into
if (t.a == 0) while (true) {}
knowing that a cant not change.
this talk offers very good explanation of these things. Jeremy Menson's talk on Java Memory Model#Google

Categories