How to trigger the reordering phenomenon in Java? - 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.

Related

Java Multi Threading Code gets stuck in a normal run mode in IDE but debug mode makes it work

I am new to Java Multi-Threading and was trying to create a program where there are 2 threads. One which prints out Odd Numbers and one which Prints out even numbers. Now, I want all numbers from 1 to 1000 printed in order such that each thread takes a turn. I have created a Turn object which is shared by the 2 objects and hence can be used for signalling 1 thread from the other! The code is given below
public class Turn {
public static int whoseTurn = 1;
public static int getWhoseTurn() {
return whoseTurn;
}
}
public class Main {
public static class EvenThread extends Thread{
#Override
public void run() {
int i = 2;
while(i < 1000){
if(Turn.getWhoseTurn() == 2) {
System.out.println(String.valueOf(i) + " is an even number ");
i = i + 2;
Turn.whoseTurn = 1;
}
}
}
}
public static class OddThread extends Thread{
#Override
public void run() {
int i = 1;
while( i < 1000){
if(Turn.getWhoseTurn() == 1) {
System.out.println(String.valueOf(i) + " is an odd number ");
i = i + 2;
Turn.whoseTurn = 2;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread evenThread = new EvenThread();
Thread oddThread = new OddThread();
oddThread.start();
evenThread.start();
Thread.sleep(10000);
evenThread.join();
oddThread.join();
}
}
I have 2 issues with this code.
The code when run in a normal run mode gets stuck anywhere from count 380 - 690. But, when run in a debug manner initially without breakpoints again gets stuck there but then if a breakpoint is added after it gets stuck, I understand where the code is and a run button again runs the code. Why does my code get stuck in a normal run mode and how do I avoid that?
Is there a race condition possible for this solution or is this solution a perfect solution for coordination between the threads? I can't think of any case where this code would fail to produce results?
The code when run in a normal run mode gets stuck anywhere from count 380 - 690. But, when run in a debug manner initially without breakpoints again gets stuck there but then if a breakpoint is added after it gets stuck, I understand where the code is and a run button again runs the code. Why does my code get stuck in a normal run mode and how do i avoid that?
^^ this happens because of busy wait. Even thread could be waiting (looping for its turn) never conceding/giving chance to Odd thread to run. And since Odd thread did not run, Even thread would not make any progress - giving the program a stuck state where no progress is being made. You could add a sleep at the end of loops in both threads to solve this (alternatively use wait/notify to avoid time wastage due to sleep). In debug mode, you essentially make a thread to pause (giving chance to other thread to proceed)
Is there a race condition possible for this solution or is this solution a perfect solution for coordination between the threads? I can't think of any case where this code would fail to produce results?
^^ multi threading programs are hard to debug and test. Currently I don't see any issues as well but would recommend comparing it with already available solutions to understand what is being differently with your logic and why.
Rishabh's answer theoretically highlights what could be going wrong. In short, just before things go wrong, one thread (can be either even or odd thread) is printing the odd/even number and then changing the whoseTurn variable so that the next thread can print the other number. However, the problem is with the latter i.e. even though the value is changed in memory, the second thread is somehow unable to read the latest value.
This is because the controlling variable whoseTurn is not a volatile variable. In java, every thread has local copy of variables in the cache. That means every read of the variable is done from the cache which may or may not be equal to the variable's value in the main memory. For Java, “volatile” tells the compiler that the value of a variable must never be cached.
For more information regarding volatile you can refer to oracle documentation page
Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable.
To verify the above, you can add the below line to your program and execute the same.
public volatile static int whoseTurn = 1;

Why does value not change inside thread?

When i assign a new value to variable it doesn't change after start(), however after i use join() it does. Why does this happen and in this case should int a be volatile or not?
class SampleThread extends Thread {
private static int a = 0;
#Override
public void run() {
a = 3;
}
public static void main(String[] args) throws InterruptedException {
Thread t2 = new Thread(new SampleThread());
t2.start();
System.out.println(a);
}
}
for seeing what is going on, try this:
...
#Override
public void run() {
System.out.println("start of Thread");
a = 3;
System.out.println("end of Thread");
}
...
only run method changed, rest of code unchanged
Yes, it needs volatile.
Every thread has an evil coin. The thread flips the coin anytime it reads or writes a field: Heads, and the thread uses its own local (to the thread) copy of it; if writing, that update simply does not reflect to all the other threads, who will still see the 'old' value, and if reading, same deal: Reads whatever it had, even though other threads updated it already. Even if they did so an hour ago. Tails, and it does refresh other threads' views of this thing, and won't use the local copy.
The coin is evil: it is not a fair coin. It will work every time today, and every time tomorrow, and every time during the test suite, and all throughout that week you have it live for the early adopting customers. And then juuust as that big client comes in and you're giving the demo? It flips to break your app every time. That kind of evil.
So, you must eliminate all coin flips, or at least ensure that the result of a coin flip does not affect your app whatsoever.
The way to do this, is to establish comes-before relationships. Between any 2 lines of java code as executed by a VM, there is a set of rules to determine if these 2 lines have such a relationship: That one is guaranteed to be run after the other. It's not about whether they did (timestamps of when they ran is completely irrelevant), it's whether the Java Memory Model decrees that such a relationship exists.
If yes, no coin is flipped: Anything the 'line that came before as per the JMM' did, is definitely visible to the line that came after. But if the JMM does not explicitly spell out that this relationship exists, the coin is flipped, and you lose.
One trivial 'comes before' relation ship is within a single thread: x = 5; System.out.println(x); trivially has such a relationship; they ran in the same thread, one came after the other. That's the freebie.
But between threads, oh dear. You need synchronized, volatile, or call code that does these things internally or has other mechanisms to ensure it (tip: There is lots of great stuff in the java.util.concurrent package, and as the name suggests, it's generally thread safe in very efficient ways. For example, an AtomicInteger is almost always far better than a volatile int, and can do far more, such as CAS operations, which volatile ints cannot do.
If you expect things in different threads to happen in a particular order -- in this case, that a = 2 is executed before `System.out.println(a)' -- then you have to write code to make that order happen.
In this trivial case, where no real work is being done, almost anything you can do makes the use of threads pointless. The main thread could 'join' the thread that's setting a to 2, but then all you've achieved is an expensive way to execute code that could be executed in a single thread.
main thread should wait that the other was executed
One solution is to use join()
class SampleThread extends Thread {
private static int a = 0;
#Override
public void run() {
a = 3;
}
public static void main(String[] args) throws InterruptedException {
Thread t2 = new Thread(new SampleThread());
t2.start();
// wait for completion of t2
t2.join()
System.out.println(a);
}
}

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

About java volatile array

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.

Visibility issue in java concurrent programming

I came across following example in book 'Java Concurrency in Practice'.
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;
}
}
Its stated further as:
NoVisibility could loop forever because the value of ready might never become
visible to the reader thread. Even more strangely, NoVisibility could print
zero because the write to ready might be made visible to the reader thread before
the write to number, a phenomenon known as reordering.
I can understand reordering issue, but I a not able to comprehend the visibility issue. Why the value of ready might never become visible to reader thread? Once main thread writes value in ready, sooner or later reader thread would get its chance to run and it can read value of ready. Why is it that change made by main thread in ready might not be visible to reader thread?
ReaderThread's run() method may never see the latest value of ready because it's free to assume and optimize that the value will not change outside of it's thread. This assumption can be taken away by using the relevant concurrency features of the language like adding the keyword volatile to ready's declaration.
I believe this is a new problem that started happening with multi-core CPUs and separate CPU caches.
There would be no need to worry if you were actually reading and modifying memory, and even with multi-CPUs you'd be safe except that each CPU now has it's own cache. The memory location would be cached and the other thread will never see it because it will be operating exclusively out of the cache.
When you make it volatile it forces both threads to go directly to memory every time--so it slows things down quite a bit but it's thread safe.

Categories