Please look at this code(taken from Effective Java book)
import java.util.concurrent.TimeUnit;
public class Main {
private static boolean stopReq;
public static void main(String[] args) throws InterruptedException {
Thread bgw = new Thread(new Runnable()
{
public void run(){
int i = 0;
while(!stopReq){ i++;}
}
});
bgw.start();
TimeUnit.SECONDS.sleep(1);
stopReq = true;
}
}
Why does the bgw thread get stuck in an infinite loop? Is it caching it's own copy of stopReq when it reached the loop? So it never sees the updated value from the other thread?
I understand the solution to this problem would be synchronizing or a volatile variable, but I am curious to why this current implementation doesn't work.
thanks
Your explanation is right.
The compiler detects than stopReq is never modified in the loop and since it is not volatile, optimizes the while(!stopReq) instruction to while(true).
Even though the value changes later, the thread does not even read it any more.
You should read more about Java Memory Model to better understand all the implications.
Shortly, the stopReq variable not being volatile or included in a synchronized block gives the VM freedom to use an optimized local storage (eg. registers etc) which is not guaranteed to propagate changes immediately across the threads.
When you declare the variable as volatile the VM will make sure that after each variable write a "memory write barrier" is inserted which will force all the local changes to be spilled to the real memory location thus making it visible to all the other threads (the same barrier is placed at the end of a synchronized block eg.)
To be very specific about your query, to take full advantage of the performance of modern multiprocessor hardware, in absence of synchronization, JVMs allowed to permit compiler to re-order operations and cache values in registers and in processor specific caches.
As main thread writes to stopReq without synchronization so because of reordering and caching the BTW thread might never see the written value and loop forever.
When you use synchronization or volatile they guarantee VISIBILITY and force compiler not to cache and flush changes to main memory.
Make stopReq to true, then it will be stopped. You are again setting the stopReq to false, due to that while loop condition is true always and it is in infinite loop.
I tested this out, and no, the variables are the same. The example also compiles for me.
The error is here:
Your while loop goes on, as long as !stopReq is true, that means stopReq is false.
And after 1 sec you set stopReq to false - this changes nothing. If you set it to true, !stopReq will become false and your loop will end.
Related
Volatile is supposed to make the Threads read the values from RAM disabling thread cache, and without volatile caching will be enabled making a thread unaware of the variable change made by another thread but this does not work for the below code.
Why does this happen and code works the same with and without volatile keyword there?
public class Racing{
private boolean won = false; //without volatile keyword
public void race() throws InterruptedException{
Thread one = new Thread(()->{
System.out.println("Player-1 is racing...");
while(!won){
won=true;
}
System.out.println("Player-1 has won...");
});
Thread two=new Thread(()->{
System.out.println("Player-2 is racing...");
while(!won){
System.out.println("Player-2 Still Racing...");
}
});
one.start();
//Thread.sleep(2000);
two.start();
}
public static void main(String k[]) {
Racing racing=new Racing();
try{
racing.race();
}
catch(InterruptedException ie){}
}
Why does this behave the same with and without volatile ?
Volatile is supposed to make the threads read the values from RAM
disabling thread cache
No, this is not accurate. It depends on the architecture where the code is running. The Java language standard itself does not state anything about how the volatile should or not be implemented.
From Myths Programmers Believe about CPU Caches can read:
As a computer engineer who has spent half a decade working with caches
at Intel and Sun, I’ve learnt a thing or two about cache-coherency.
(...)
For another, if volatile variables were truly written/read from main-memory > every single time, they would be horrendously slow – main-memory references are > 200x slower than L1 cache references. In reality, volatile-reads (in Java) can > often be just as cheap as a L1 cache reference, putting to rest the notion that volatile forces reads/writes all the way to main memory. If you’ve been avoiding the use of volatiles because of performance concerns, you might have been a victim of the above misconceptions.
Unfortunately, there still are several articles online propagating this inaccuracy (i.e., that volatile forces variables to be read from main memory).
Accordingly to the language standard (§17.4):
A field may be declared volatile, in which case the Java Memory Model
ensures that all threads see a consistent value for the variable
So informally, all threads will have a view of the most updated value of that variable. There is nothing about how the hardware should enforce such constrain.
Why does this happen and code works same with and without volatile
Well (in your case) without the volatile is undefined behavior, meaning you might or not see the most updated value of the flag won, consequently, theoretically the race condition is still there. However, because you have added the following statement
System.out.println("Player-2 Still Racing...");
in:
Thread two = new Thread(()->{
System.out.println("Player-2 is racing...");
while(!won){
System.out.println("Player-2 Still Racing...");
}
});
two things will happen, you will avoid the Spin on field problem, and second if one looks at the System.out.println code:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
one can see that there is a synchronized being called, which will increase the likelihood that the threads will be reading the most updated value of the field flag (before the called to the println method). However, even that might change based on the JVM implementation.
Without volatile, there is no guarantee that another thread will see updates written to a variable. That does not mean that another thread will not see those updates if the value is not volatile. Other threads may eventually see the modified value.
In your example, you are using System.out.printlns, which contain memory barriers. That means once the println works, all variables updated before that point are visible to all the threads. The program might work differently if you do not print anything.
I've encountered this code in a book. It states NoVisibility could loop forever because the value of ready might never become
visible to the reader thread.
I'm confused by this statement. In order for the loop to run forever, ready must always be false, which is the default value. This means it must fail at executing ready = true; because the reader thread will always read the ready variable from memory. the assignment happens in CPU and it must have some problem in flushing the data back to Main Memory. I think I need some explanation on a situation how it can fail, or I may have missed some other part.
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;
}
}
Your understanding is flawed. You are assuming that Java will behave intuitively here. In fact, it may not. And, indeed, the Java Language specification allows non-intuitive behavior if you don't follow the rules.
To be more specific, in your example it is NOT GUARANTEED that the second thread will see the results of the first thread's assignment to ready1. This is due to such things as:
The compiler caching the value of ready in a register in the first or second thread.
The compiler not including instructions to force the write to be flushed from one core's memory cache to main memory, or similar.
If you want a guarantee that the second thread will see the result of the write then either reads and writes of ready by the two threads must be (properly) synchronized, or the ready variable must be declared to be volatile.
So ...
This means it must fail at executing ready = true; because the reader thread will always read the ready variable from memory.
is incorrect. The "because" is not guaranteed by the Java language specification in this example.
Yes. It is nonintuitive. Relying on your intuition based on your understanding of single-threaded programs is not reliable. If you want to want to understand what is and is not guaranteed, please study the specification of the "Java Memory Model" in Section 17.4 of the JLS.
In short, the book is correct.
1 - It might see the results immediately, or after a short or long delay. Or it might never see them. And the behavior is liable to vary from one system to the next, and with versions of the Java platform. So your program that (by luck) works all of the time on one system may not always work on another system.
The value of ready may be updated but the other thread may never know about it. There you need volatile variables! A thread assumes that the variable is only used by this and only thread. So, it reads its value from the stack that it created.
private static volatile boolean ready;
What volatile does is that it says to your program to ready from the memory, not from the stack.
Actually what jvm does is it translates:
while(flag){...}
To:
if(flag){
while(true){
}
The stack is created when the thread is created. It collectes the values of the variables in order to use them later.
This is what I have understand, correct me if I am wrong!
In Effective Java: item 66, Joshua Bloch gave an example about life failure:
// Broken! - How long would you expect this program to run
class StopThread {
private static boolean stopRequested = false;
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested) {
i++;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
As Joshua Bloch said, this program would not terminate.
But, if I change i++ into System.out.println(i++), it terminates successfully!
I can't figure out how it happens!
The problem is related to the memory value of the variable stopRequest.
This variable is not defined as volatile.
If you have a two processors the inner thread check the value of stopRequest taken from its registry.
The main thread alter the value of stopRequest in the registry of the other processor.
So the main thread modify a value of stopRequest but the thread see only a copy of it that never changes.
Modified after take a look at the source code of PrintStream (thanks to the commend of ΔλЛ): Using a System.out.print command will use an explicit synchronized block to print the value passed to it this will grant that the value of stopRequest is taken from the main memory and not from the registry of the processor.
Adding a volatile keyword will inform the JVM to take the value from the main memory instead from the registries of the processors and it solve the problem.
Also using the keyword synchronized will solve this problem because any variable used in the synchronized block is taken and update the main memory.
Memory model without volatile (Main thread use Processor 1 and explicit thread use Processor 2)
Processor 1 Processor 2 Main memory
----------- ----------- -----------
false false false
true false true // After setting
//stopRequest to true
Defining stopRequest as volatile where all threads read stopRequest from main memory.
Processor 1 Processor 2 Main memory
----------- ----------- -----------
NA NA false
NA NA true // After setting
//stopRequest to true
Since you are not telling the thread that stopRequested is a value that can be modified from outside that thread there are no guarantees that the while will evaluate to the most recent value of the variable.
This is why the volatile keyword is useful in this situation, because it will explicitly enforce that stopRequested value, when read, will be the most recent value set by any thread.
There are further considerations, actually from the point of view of the thread, stopRequested is a loop invariant, since it is never set by only read, so optimization choices should be considered too: if a value is thought not to be modified then there is no reason to evaluate it on each iteration.
tl;dr: It's most likely an "accidental" side effect of println being synchronized.
First, realize that it's not the case that the thread is guaranteed not to finish; it's that it's not guaranteed that it will finish. In other words, the race condition on stopRequested — caused by the fact that one thread is writing to it, and another thread is reading from it, and there's no synchronization between the two threads — means that the JVM may, but is not required to, let the reader see what the writer has done.
So, why does System.out.println change this? Because it's a synchronized method. This doesn't actually give you any guarantees about stopRequested as far as the JLS is concerned, but it does mean that the JVM has to do some things, like acquiring a(n unrelated) lock, and establishing (unrelated) happens-before edges, that make it more likely that the write to stopRequested will be seen across threads.
System.out.println() requests a resource to write on the console, which in itself a blocking method… meaning, it will block the backgroundThread() to print() on the console. This is similar to sending an interrupt to it.
Thus, backgroundThread() will become aware of the change in the value of the boolean and stop executing, thereby terminating the Daemon.
I am new to Java, I am currently learning about volatile. Say I have the following code:
public class Test
{
private static boolean b = false;
public static void main(String[] args) throws Exception
{
new Thread(new Runnable()
{
public void run()
{
while(true)
{
b = true;
}
}
}).start();
// Give time for thread to start
Thread.sleep(2000);
System.out.println(b);
}
}
Output:
true
This code has two threads (the main thread and another thread). Why is the other thread able to modify the value of b, shouldn't b be volatile in order for this to happen?
The volatile keyword guarantees that changes are visible amongst multiple threads, but you're interpreting that to mean that opposite is also true; that the absence of the volatile keyword guarantees isolation between threads, and there's no such guarantee.
Also, while your code example is multi-threaded, it isn't necessarily concurrent. It could be that the values were cached per-thread, but there was enough time for the JVM to propagate the change before you printed the result.
You are right that with volatile, you can ensure/guarantee that your 2 threads will see the appropriate value from main memory at all times, and never a thread-specific cached version of it.
Without volatile, you lose that guarantee. And each thread is working with its own cached version of the value.
However, there is nothing preventing the 2 threads from resynchronizing their memory if and when they feel like it, and eventually viewing the same value (maybe). It's just that you can't guarantee that it will happen, and you most certainly cannot guarantee when it will happen. But it can happen at some indeterminate point in time.
The point is that your code may work sometimes, and sometimes not. But even if every time you run it on your personal computer, is seems like it's reading the variable properly, it's very likely that this same code will break on a different machine. So you are taking big risks.
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.