Java volatile reordering prevention scope - java

Writes and reads to a volatile field prevent reordering of reads/writes before and after the volatile field respectively. Variable reads/writes before a write to a volatile variable can not be reordered to happen after it, and reads/writes after a read from a volatile variable can not be reordered to happen before it. But what is the scope of this prohibition? As I understand volatile variable prevents reordering only inside the block where it is used, am I right?
Let me give a concrete example for clarity. Let's say we have such code:
int i,j,k;
volatile int l;
boolean flag = true;
void someMethod() {
int i = 1;
if (flag) {
j = 2;
}
if (flag) {
k = 3;
l = 4;
}
}
Obviously, write to l will prevent write to k from reordering, but will it prevent reordering of writes to i and j in respect to l? In other words can writes to i and j happen after write to l?
UPDATE 1
Thanks guys for taking your time and answering my question - I appreciate this. The problem is you're answering the wrong question. My question is about scope, not about the basic concept. The question is basically how far in code does complier guarantee the "happens before" relation to the volatile field.
Obviously compiler can guarantee that inside the same code block, but what about enclosing blocks and peer blocks - that's what my question is about. #Stephen C said, that volatile guarantees happen before behavior inside the whole method's body, even in the enclosing block, but I can not find any confirmation to that. Is he right, is there a confirmation somewhere?
Let me give yet another concrete example about scoping to clarify things:
setVolatile() {
l = 5;
}
callTheSet() {
i = 6;
setVolatile();
}
Will compiler prohibit reordering of i write in this case? Or maybe compiler can not/is not programmed to track what happens in other methods in case of volatile, and i write can be reordered to happen before setVolatile()? Or maybe compiler doesn't reorder method calls at all?
I mean there is got to be a point somewhere, when compiler will not be able to track if some code should happen before some volatile field write. Otherwise one volatile field write/read might affect ordering of half of a program, if not more. This is a rare case, but it is possible.
Moreover, look at this quote
Under the new memory model, it is still true that volatile variables cannot be reordered with each other. The difference is that it is now no longer so easy to reorder normal field accesses around them.
"Around them". This phrase implies, that there is a scope where volatile field can prevent reordering.

Obviously, write to l will prevent write to k from reordering, but will it prevent reordering of writes to i and j?
It is not entirely clear what you mean by reordering; see my comments above.
However, in the Java 5+ memory model, we can say that the writes to i and j that happened before the write to l will be visible to another thread after it has read l ... provided that nothing writes i and j after write to l.
This does have the effect of constraining any reordering of the instructions that write to i and j. Specifically, they can't be moved to after the memory write barrier following the write to l, because that could lead them to not being visible to the second thread.
But what is the scope of this prohibition?
There isn't a prohibition per se.
You need to understand that instructions, reordering and memory barriers are just details of a specific way of implementing the Java memory model. The model is actually defined in terms of what is guaranteed to be visible in any "well-formed execution".
As I understand volatile prevents reordering inside the block where it is used, am I right?
Actually, no. The blocks don't come into the consideration. What matters is the (program source code) order of the statements within the method.
#Stephen C said, that volatile guarantees happen before behavior inside the whole method's body, even in the enclosing block, but I can not find any confirmation to that.
The confirmation is JLS 17.4.3. It states the following:
Among all the inter-thread actions performed by each thread t, the program order of t is a total order that reflects the order in which these actions would be performed according to the intra-thread semantics of t.
A set of actions is sequentially consistent if all actions occur in a total order (the execution order) that is consistent with program order, and furthermore, each read r of a variable v sees the value written by the write w to v such that:
w comes before r in the execution order, and
there is no other write w' such that w comes before w' and w' comes before r in the execution order.
Sequential consistency is a very strong guarantee that is made about visibility and ordering in an execution of a program. Within a sequentially consistent execution, there is a total order over all individual actions (such as reads and writes) which is consistent with the order of the program, and each individual action is atomic and is immediately visible to every thread.
If a program has no data races, then all executions of the program will appear to be sequentially consistent.
Notice that there is NO mention of blocks or scopes in this definition.

EDIT 2
The volatile ONLY gaurentee the happens-before relation.
Why it reorder in single thread
Considered we have two fields:
int i = 0;
int j = 0;
We have a method to write them
void write() {
i = 1;
j = 2;
}
As you know, compiler may reorder them. That is because compiler think it is not matter access which first. Because in single thread, they are 'happen together'.
Why can't reorder in multi thread
But now we have another method to read them in another thread:
void read() {
if(j==2) {
assert i==1;
}
}
If compiler still reorder it, this assert may fail. That means j has been 2, but i unexpectly is not 1. Which seems i=1 is happens after assert i==1.
What volatile do
The volatile only gaurantee the happens-before relation.
Now we add volatile
volatile int j = 0;
When we observe j==2 is true, that means j=2 is happened and i=2 is before it, it must happened. So the assert will never fail now.
'Prventing reorder' is just an approach that compiler to provide that guarantee.
Conclusion
The only things you should now is happens-before. Please refer to the link below of java specification. The reordering or not is just a side effect of this guarantee.
Answer for you question
Since l is volatile, acccess to i and j always before access to l in the someMethod. The fact is, every thing before the line l=4 will happen before before it.
EDIT 1
Since the post has been edit. Here is further explasion.
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
happens-before means:
If one action happens-before another, then the first is visible to and ordered before the second.
So the access to i and j happen-before access to l.
reference: https://docs.oracle.com/javase/specs/jls/se10/html/jls-17.html#jls-17.4.5
Origin answer
No, the volatile only protect itself, though it is not easy to reorder field access near volatile.
Under the new memory model, it is still true that volatile variables cannot be reordered with each other. The difference is that it is now no longer so easy to reorder normal field accesses around them. Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire. In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
The volatile keyword only guarantee that:
A write to a volatile field happens before every subsequent read of that same volatile.
reference: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile

I am curious to know how volatile variable affects OTHER fields
Volatile variables do affect the other fields. JIT compiler can reorder the instructions if he thinks that reordering will not have any impact on the execution output. So if you have 6 independent variable stores JIT can reorder the instructions.
However if you make a variable volatile i.e. in your case variable l then JIT will not reorder any variable STORES after the volatile STORE. And I think that makes sense because in a multithreaded program if I get the value of variable l as 4, then I should get i as 1, because in my program i was written before l and which eventually is Program Order Semantics (If I am not wrong).
Note that volatile variables does two things:
Compiler will not reorder any stores after volatile store / not reorder any reads before volatile read.
Flushes the Load/Store buffer so that all the processor can see the changes.
EDIT:
Good blog here: http://jpbempel.blogspot.com/2013/05/volatile-and-memory-barriers.html

Maybe I know the "real scope" you are in dout.
Two types of reorder is the main reason of unordering instruction result:
1. Compiler optimization
2. Cpu processor recordering(maily caused by cache and main memory synchronize)
volatile keyword first need to confirm the flushing of volatile variable, at the meantime, other variables are also flushed to main memory.But because of compiler reordering, some writable instructions before the volatile valatile variable may be reordered after the volatile variable, the reader may be confused to read not the real time other variable values which is before the volatile variable in program order, so the rule of "variables writting instruction before the volatile variable is forced to run before the volatile" is made.This optimazation is done by Java Compiler or JIT.
The main point is optimization of compiler in instructions,like finding dead code , instruction reorder operation, the instructions code range is always a "basic block"(Except some other constant propagation optimization, etc.). A basic block is an set of instructions without jmp instruction inside, so this is a basic block. So in my opinion, the reorder operation is fixed in the range basic block.
the basic block in source code is always a block or the body of a method.
And also because java does not have inline function, the method call is used by dynamic invoke method instruction, the reorder operation should not be across two method.
So, the scope will not be larger than a "method body", or maybe only a area of "for" body , it's the basic block range.
This is all my thought, I'm not sure if it is right, someone can help to make it more accurate.

Related

Java volatile and happens-before scope

The tutorial http://tutorials.jenkov.com/java-concurrency/volatile.html says
Reads from and writes to other variables cannot be reordered to occur
after a write to a volatile variable, if the reads / writes originally
occurred before the write to the volatile variable. The reads / writes
before a write to a volatile variable are guaranteed to "happen
before" the write to the volatile variable.
What is meant by "before the write to the volatile variable"? Does it mean previous read/writes in the same method where we are writing to the volatile variable? Or is it a larger scope (also in methods higher up the call stack)?
JVM can reorder operations. For example if we have i, j variables and code
i = 1;
j = 2;
JVM can run this in reordered manner
j = 2;
i = 1;
But if the j variable marked as volatile then JVM runs operations only as
i = 1;
j = 2;
write to i "happens before the write to the volatile variable" j.
The JVM ensures that writes to a volatile variable happens-before any reads from it. Take two threads. It's guarateed that for a single thread, the execution follows an as-if-serial semantics. Basically you can assume that there is an implicit happens-before relationship b/w two executions in the same thread (the compiler is still free to reorder instructions). Basically a single thread has a total order b/w its instructions governed by the happens-before relationship trivially.
A multi-threaded program has many such partial orders (every thread has a total order in the local instruction set but there is no order globally across threads) but not a total order b/w the global instruction set. Synchronisation is all about giving your program as much total order as possible.
Coming back to volatile variables, when a thread reads from it, the JVM ensures that all writes to it happened before the read. Now because of this order, everything the writing thread did before it wrote to the variable become visible to the thread reading from it. So yes, to answer your question, even variables up in the call stack should be visible to the reading thread.
I'll try to draw a visual picture. The two threads can be imagined as two parallel rails, and write to a volatile variable can be one of the sleepers b/w them. You basically get a
A -----
|
|
------- B
shaped total order b/w the two threads of execution. Everything in A before the sleeper should be visible to B after the sleeper because of this total order.
The JMM is defined in terms of happens before relation which we'll call ->. If a->b, then the b should see everything of a. This means that there are constraints on reordering loads/stores.
If a is a volatile write and b is a subsequent volatile read of the same variable, then a->b. This is called the volatile variable rule.
If a occurs before b in the code, then a->b. This is called the program order rule.
If a->b and b->c, then a->c. This is called the transitivity rule.
So lets apply this to a simple example:
int a;
volatile int b;
thread1(){
a=1;
b=1
}
thread2(){
int rb=b;
int ra=a;
if(rb==1 and ra==0) print("violation");
}
So the question is if thread2 sees rb=1,will it see ra=1?
a=1->b=1 due to program order rule.
b=1->rb=b (since we see the value 1) due to the volatile variable rule.
rb=b->ra=a due to program order rule.
Now we can apply the transitivity rule twice and we can conclude that that a=1->ra=a. And therefor ra needs to be 1.
This means that:
a=1 and b=1 can't be reordered.
rb=b and ra=a can't be reordered
otherwise we could end up with an rb=1 and ra=0.

Can't understand example of volatile in Java specification

I got general understanding what volatile means in Java. But reading
Java SE Specification 8.3.1.4 I have a problem understanding the text beneath that certain volatile example.
class Test {
static volatile int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
This allows method one and method two to be executed concurrently, but
guarantees that accesses to the shared values for i and j occur
exactly as many times, and in exactly the same order, as they appear
to occur during execution of the program text by each thread.
Therefore, the shared value for j is never greater than that for i,
because each update to i must be reflected in the shared value for i
before the update to j occurs. It is possible, however, that any given
invocation of method two might observe a value for j that is much
greater than the value observed for i, because method one might be
executed many times between the moment when method two fetches the
value of i and the moment when method two fetches the value of j.
How is
j never greater than i
, but at the same time
any given invocation of method two might observe a value for j that is
much greater than the value observed for i
??
Looks like contradiction.
I got j greater than i after running sample program. Why use volatile then? It gives almost the same result without volatile (also i can be greater than j, one of previous examples in specs). Why is this example here as an alternative to synchronized?
At any one time, then j is not greater than i.
This is different from what method two observes because it is accessing the variables i and j at different times. i is accessed first, and then j is accessed slightly later.
This isn't a direct alternative to the synchronized version because the behavior is different. One difference from not using volatile is that without volatile, values of 0 could always be printed. The increment doesn't ever need to be visible.
The example demonstrates the ordering of volatile accesses. An example that requires this could be something like:
volatile boolean flag = false;
volatile int value;
// Thread 1
if(!flag) {
value = ...;
flag = true;
}
// Thread 2
if(flag) {
System.out.println(value);
flag = false;
}
and thread 2 reads the value that thread 1 set rather than an old value.
I'd like to propose that it's a mistake and the examples were supposed to print j before i:
static void two() {
System.out.println("j=" + j + " i=" + i);
}
The novelty in the first example is that, due to update reordering, j can be greater than i even when observed first.
The final example now makes perfect sense with some minor edits to the explanation (edits and commentary in brackets):
This allows method one and method two to be executed concurrently, but guarantees that accesses to the shared values for i and j occur exactly as many times, and in exactly the same order, as they appear to occur during execution of the program text by each thread. Therefore, the shared value for j is never [observed to be] greater than that for i, because each update to i must be reflected in the shared value for i before the update to j occurs. It is possible, however, that any given invocation of method two might observe a value for [i] that is much greater than the value observed for [j], because method one might be executed many times between the moment when method two fetches the value of [j] and the moment when method two fetches the value of [i].
The key point here is that the second update will never be observed before the first update, when using volatile. The last sentence about the gap between the two reads is entirely parenthetical, and i and j were swapped to conform to the erroneous example.
I think the point of the example is to emphasize that you need to take care and ensure the order when using volatile; the behavior may be counter-intuitive and the example demonstrates it.
I agree that the wording there is a bit obscure and it is possible to provide more explicit and clear example for multiple cases, but there is no contradiction.
The shared value is the value at the same moment. If two threads read values of i and of j at exactly the same moment, the value of j will never be observed greater than i. volatile guarantees keeping order of reads and updates as in the code.
However, in the sample, print + i and + j are two different operations separated by an arbitrary amount of time; hence, j can be observed larger than i, because it can be updated arbitrary number of times after the read of i and before the read of j.
The point of using volatile is that when you concurrently update and access volatile variables with the right order, you can make assumptions that are not possible in principle without volatile.
In the sample above, the order of access in two() does not allow to conclude with a confidence which variable is greater or equal.
Consider, however, if the sample was changed to System.out.println("j=" + j + " i=" + i);
Here you can assert with a confidence that the printed value of j is never larger than the printed value of i. This assumption will not hold without volatile for two reasons.
First, updates i++ and j++ can be executed by compiler and hardware in an arbitrary order and in reality may execute as j++;i++. If from other thread you then access j and i after j++ but before i++, you can observe, say, j=1 and i=0, regardless of the access order. volatile guarantees that this will not happen and it will execute operations in the order that is written in your source.
Second, volatile guarantees that another thread will see most recent values changed by another thread, as long as it accesses it in the later point of time after the last update. Without volatile, there can be no assumptions about the observed value. In theory, the value can stay for another thread zero forever. The program may print two zeros, zero and an arbitrary number, etc. from past updates; the observed value in other threads may be less than the current value that the updater thread sees after an update. volatile guarantees that you will see the value in a second thread after the update in the first.
While the second guarantee may seem as a consequence of the first (the order guarantee), they are in fact orthogonal.
Regarding synchronized, it allows to execute a sequence of non-atomic operations, like i++;j++ as an atomic operation, e.g. if one thread does synchronized i++;j++ and another does synchronized System.out.println("i=" + i + " j=" + j);, the first thread may not perform increment sequence while the second prints and the result will be correct.
But this comes at a cost. First, synhronized has a performance penalty by itself. Second, more important, not always such behavior is required and the blocked thread wastes time, reducing the system throughput (e.g. you can do so many i++;j++; during System.out).
How is j never greater than i?
Let's say you execute one() only once. During the execution of this method, i is always incremented before j as the increment operations happen one after the other.
If you are executing one() concurrently, each individual method call will wait for other methods in the execution queue to finish writing their values to i or j, depending on which variable the currently executing method is trying to increment. So, all writes to i happen one after the other, and all writes to j happen one after the other. And since within the method body itself i is incremented before j, at a given instant, j will never be greater than i.
any given invocation of method two might observe a value for j that is much greater than the value observed for i, how?
If method one() is being executed in the background while you call two(), between the time when i is read and then j is read, the method one can be executed multiple times. So, when the value of i is read it could be the result some invocation of one() that happened at time t=0, and when then value of j is read, it could be the result of an invocation of one() that happened later in time, for example at t=10. Hence, j can be greater than i in this case in the println statement.
Why use volatile in lieu of synchronized?
I will not list all the reasons why anyone should use volatile instead of a synchronized block. But bear in mind that volatile guarantees atomic access to that particular field alone, and does not ensure the atomic execution of a block of code that is not marked as synchronized. In this example, access to i and j are synchronized, but the overall operation {i++;j++} isn't synchronized hence it apparently (I use apparently since it is not exactly the same but looks similar) gives the same results as without using the volatile keyword.
How is
j never greater than i
, but at the same time
any given invocation of method two might observe a value for j that is much >>greater than the value observed for i
??
The first statement is always true at any given moment in the program's execution, and the second statement may be true for any given interval in the program's execution.
When a volatile variable is written to, writes to both it and everything before it must become visible to other threads (In Java 5+, at least. The explanation doesn't really change much for versions of Java before that, though). Thus, the increment of i must be visible by the time j is incremented, meaning that j can never appear greater than i to other threads.
The reads of i and j, though, are not guaranteed to occur at a single moment in the program execution. The read of i and j may appear to occur very close to each other to the thread executing two(), but in reality some arbitrary amount of time may have passed between the reads. For example, two() may read i when i = 5 and j = 5, but then get "frozen" while other threads execute, changing the values of i and j to, say, 20 and 19, respectively. When two() resumes, it picks up where it left off and reads j, which now has a value of 19. two() doesn't re-read i because as far as it is concerned there was no break in execution, so there is no need to undergo the extra work.
Why use volatile then?
While both volatile and synchronized provide visibility guarantees, the precise semantics are slightly different. volatile guarantees that changes made to the variable will be instantly visible to all threads, while synchronized guarantees that changes made in its block will be visible to all threads as long as they synchronize on the same lock. synchronized also provides additional atomicity guarantees that volatile does not.
Why is this example here as an alternative to synchronized?
volatile is a viable alternative to synchronized only if one() is executed by a single thread, which is the case here. In this case, only a single thread is ever writing to i and j, so there is no need for the atomicity guarantees synchronized provides. If one() were executed by multiple threads, volatile wouldn't work because the read-add-store operations that make up an increment must occur atomically, and volatile does not guarantee that.
This program does guarantee that method two() observes j >= i-1 (not considering overflow).
Without volatile, the observed values of i,j could be all over the place.
The statement
the shared value for j is never greater than that for i
is very informal, because it means "at the same time", which is not a defined concept in JMM.
The core principle of JMM is about "sequential consistency". The driving motivation of JMM is
JLS#17 - If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent
In the following program
void f()
{
int x=0, y=0;
x++;
print( x>y );
y++
}
x>y will always be observed as true. It has to be, if we follow the sequence of actions. Otherwise, there is really no way for us to reason about any (imperative) code. That is "sequential consistency".
"Sequential consistency" is an observed property, it doesn't have to coincide with "real" actions (whatever that means). It is entirely possible that x>y is evaluated to be true by JVM before x is actually incremented (or at all). As long as JVM can guarantee observed sequential consistency, it can optimize actual execution anyway it can, e.g. execute code out of order.
But this is for a singlet thread. If multiple threads are reading/writing shared variables, such optimizations of course will completely wreck sequential consistency. We cannot reason about program behavior by thinking of interleaving actions from multiple threads (with actions in the same thread following intra-thread sequence).
If we want to guarantee inter-thread sequential consistency of any multi-thread code, we must abandon the optimization techniques developed for single thread. That is going to have severe performance penalty for most programs. And it is also uncalled for -- data exchange among threads is rather rare.
Therefore, special instructions are created just for establishing inter-thread sequential consistency when it is needed. Volatile reads and writes are such actions. All volatile reads and writes obey inter-thread sequential consistency. In this case, it guarantees that j >= i-1 in two().
All dependes on how you are using it. The 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 e.g. read and write in an int or a boolean variable then you can declare them as volatile variable.
From Java 5 along with major changes like Autoboxing, Enum, Generics and Variable arguments , Java introduces some change in Java Memory Model (JMM), Which guarantees visibility of changes made from one thread to another also as "happens-before" which solves the problem of memory writes that happen in one thread can "leak through" and be seen by another thread.
The Java volatile keyword cannot be used with method or class and it can only be used with a variable. Java volatile keyword also guarantees visibility and ordering, after Java 5 write to any volatile variable happens before any read into the volatile variable. By the way use of volatile keyword also prevents compiler or JVM from the reordering of code or moving away them from synchronization barrier.
Important points on Volatile keyword in Java
The volatile keyword in Java is only application to a variable and using volatile keyword with class and method is illegal.
volatile keyword in Java guarantees that value of the volatile variable will always be read from main memory and not from Thread's local cache.
In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).
Using the volatile keyword in Java on variables reduces the risk of memory consistency errors because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.

Java volatile effect on other variables [duplicate]

So I am reading this book titled Java Concurrency in Practice and I am stuck on this one explanation which I cannot seem to comprehend without an example. This is the quote:
When thread A writes to a volatile
variable and subsequently thread B
reads that same variable, the values
of all variables that were visible to
A prior to writing to the volatile
variable become visible to B after
reading the volatile variable.
Can someone give me a counterexample of why "the values of ALL variables that were visible to A prior to writing to the volatile variable become visible to B AFTER reading the volatile variable"?
I am confused why all other non-volatile variables do not become visible to B before reading the volatile variable?
Declaring a volatile Java variable means:
The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory".
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.
Just for your reference, When is volatile needed ?
When multiple threads using the same
variable, each thread will have its
own copy of the local cache for that
variable. So, when it's updating the
value, it is actually updated in the
local cache not in the main variable
memory. The other thread which is
using the same variable doesn't know
anything about the values changed by
the another thread. To avoid this
problem, if you declare a variable as
volatile, then it will not be stored
in the local cache. Whenever thread
are updating the values, it is updated
to the main memory. So, other threads
can access the updated value.
From JLS §17.4.7 Well-Formed Executions
We only consider well-formed
executions. An execution E = < P, A,
po, so, W, V, sw, hb > is well formed
if the following conditions are true:
Each read sees a write to the same
variable in the execution. All reads
and writes of volatile variables are
volatile actions. For all reads r in
A, we have W(r) in A and W(r).v = r.v.
The variable r.v is volatile if and
only if r is a volatile read, and the
variable w.v is volatile if and only
if w is a volatile write.
Happens-before order is a partial
order. Happens-before order is given
by the transitive closure of
synchronizes-with edges and program
order. It must be a valid partial
order: reflexive, transitive and
antisymmetric.
The execution obeys
intra-thread consistency. For each
thread t, the actions performed by t
in A are the same as would be
generated by that thread in
program-order in isolation, with each
write wwriting the value V(w), given
that each read r sees the value
V(W(r)). Values seen by each read are
determined by the memory model. The
program order given must reflect the
program order in which the actions
would be performed according to the
intra-thread semantics of P.
The execution is happens-before consistent
(§17.4.6).
The execution obeys
synchronization-order consistency. For
all volatile reads r in A, it is not
the case that either so(r, W(r)) or
that there exists a write win A such
that w.v = r.v and so(W(r), w) and
so(w, r).
Useful Link : What do we really know about non-blocking concurrency in Java?
Thread B may have a CPU-local cache of those variables. A read of a volatile variable ensures that any intermediate cache flush from a previous write to the volatile is observed.
For an example, read the following link, which concludes with "Fixing Double-Checked Locking using Volatile":
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
If a variable is non-volatile, then the compiler and the CPU, may re-order instructions freely as they see fit, in order to optimize for performance.
If the variable is now declared volatile, then the compiler no longer attempts to optimize accesses (reads and writes) to that variable. It may however continue to optimize access for other variables.
At runtime, when a volatile variable is accessed, the JVM generates appropriate memory barrier instructions to the CPU. The memory barrier serves the same purpose - the CPU is also prevent from re-ordering instructions.
When a volatile variable is written to (by thread A), all writes to any other variable are completed (or will atleast appear to be) and made visible to A before the write to the volatile variable; this is often due to a memory-write barrier instruction. Likewise, any reads on other variables, will be completed (or will appear to be) before the
read (by thread B); this is often due to a memory-read barrier instruction. This ordering of instructions that is enforced by the barrier(s), will mean that all writes visible to A, will be visible B. This however, does not mean that any re-ordering of instructions has not happened (the compiler may have performed re-ordering for other instructions); it simply means that if any writes visible to A have occurred, it would be visible to B. In simpler terms, it means that strict-program order is not maintained.
I will point to this writeup on Memory Barriers and JVM Concurrency, if you want to understand how the JVM issues memory barrier instructions, in finer detail.
Related questions
What is a memory fence?
What are some tricks that a processor does to optimize code?
Threads are allowed to cache variable values that other threads may have since updated since they read them. The volatile keyword forces all threads to not cache values.
This is simply an additional bonus the memory model gives you, if you work with volatile variables.
Normally (i.e. in the absence of volatile variables and synchronization), the VM can make variables from one thread visible to other threads in any order it wants, or not at all. E.g. the reading thread could read some mixture of earlier versions of another threads variable assignments. This is caused by the threads being maybe run on different CPUs with their own caches, which are only sometimes copied to the "main memory", and additionally by code reordering for optimization purposes.
If you used a volatile variable, as soon as thread B read some value X from it, the VM makes sure that anything which thread A has written before it wrote X is also visible to B. (And also everything which A got guaranteed as visible, transitively).
Similar guarantees are given for synchronized blocks and other types of locks.

Some doubts about volatile and Atomic classes?

i am going thru Java threads book. I came across this statement
Statement 1:- "volatile variables can be safely used only for single load or store operation and can't be
applied to long or double variales. These restrictions make the use of volatile variables uncommon"
I did not get what does single load or store operation mean here? why volatile can't be
applied to long or double variales?
Statement 2:- "A Volatile integer can not be used with the ++ operator because ++ operator contains
multiple instructions.The AtomicInteger class has a method that allows the integer it holds to be
incremented atomically."
Why Volatile integer can not be used with the ++ operator and how AtomicInteger addresses it?
Statement 1:- "volatile variables can be safely used only for single load or store operation and can't be applied to long or double variales. These restrictions make the use of volatile variables uncommon"
What?! I believe this is simply flat-out wrong. Maybe your book is out of date.
Statement 2:- "A Volatile integer can not be used with the ++ operator because ++ operator contains multiple instructions.The AtomicInteger class has a method that allows the integer it holds to be incremented atomically."
Exactly what it says. The ++ operator actually translates to machine code like this (in Java-like pseudocode):
sync_CPU_caches();
int processorRegister = variable;
processorRegister = processorRegister + 1;
variable = processorRegister;
sync_CPU_caches();
This is not thread-safe, because even though it has a memory barrier, and reads atomically, and writes atomically, it is not guaranteed that you won't get a thread switch in the middle, and processor registers are local to a CPU core (think of them as like "local variables" inside the CPU core). But an AtomicInteger is thread-safe - it probably is implemented using special machine code instructions such as compare-and-swap.
The main purpose of volatile variables is not to cause immediate thread-safe access to that variable, but to ensure a so called happens-before safety.
Theoretically a call to
volatile int i = 0;
and
int i = 0;
has no difference, as a 32-bit word is written atomically anyways (on 32 bit and higher machines to be correct). Since pointers are 32/64 bit ints as well internally, there is basically only one operation that volatile makes atomically, and that is if you use a 64 bit long in a 32 bit environment.
The happens-before however is something that actually messes up the above example. To understand this you need to know that threads don't use the actual memory of the variable in question but might make copies of it to speed up execution and can re-order the statements for optimization. Now if you have something like:
Thread A: value = 1; doIt = true;
Thread B: if (doIt) { doDoIt(value); }
It is possible that in Thread B doIt is true, but value is not yet 1, because the order of execution might have been changed by the JVM, or the new value has just not yet been broadcasted to the copy of Thread B's value.
If doIt is declared volatile instead, then at the moment of accessing it, the JVM ensures that all code before that access has already been executed and broadcasted. So the above example is the actual reason to use volatile.

Does volatile influence non-volatile variables?

Okay, suppose I have a bunch of variables, one of them declared volatile:
int a;
int b;
int c;
volatile int v;
If one thread writes to all four variables (writing to v last), and another thread reads from all four variables (reading from v first), does that second thread see the values written to a, b and c by the first thread, even though they are not themselves declared volatile? Or can it possibly see stale values?
Since there seems to be some confusion: I'm not deliberately trying to do something unsafe. I just want to understand the Java memory model and the semantics of the volatile keyword. Pure curiosity.
I'm going to speak to what I think you may really be probing about—piggybacking synchronization.
The technique that it looks like you're trying to use involves using one volatile variable as a synchronization guard in concert with one or more other non-volatile variables. This technique is applicable when the following conditions hold true:
Only one thread will write to the set of values meant to be guarded.
The threads reading the set of values will read them only if the volatile guard value meets some criteria.
You don't mention the second condition holding true for your example, but we can examine it anyway. The model for the writer is as follows:
Write to all the non-volatile variables, assuming that no other thread will try to read them.
Once complete, write a value to the volatile guard variable that indicates that the readers' criteria is met.
The readers operate as follows:
Read the volatile guard variable at any time, and if its value meets the criteria, then
Read the other non-volatile variables.
The readers must not read the other non-volatile variables if the volatile guard variable does not yet indicate a proper value.
The guard variable is acting as a gate. It's closed until the writer sets it to a particular value, or set of values that all meet the criteria of indicating that the gate is now open. The non-volatile variables are guarded behind the gate. The reader is not permitted to read them until the gate opens. Once the gate is open, the reader will see a consistent view of the set of non-volatile variables.
Note that it is not safe to run this protocol repeatedly. The writer can't keep changing the non-volatile variables once it's opened the gate. At that point, multiple reader threads may be reading those other variables, and they can—though are not guaranteed—see updates to those variables. Seeing some but not all of those updates would yield inconsistent views of the set.
Backing up, the trick here is to control access to a set of variables without either
creating a structure to hold them all, to which an atomic reference could be swapped, um, atomically, or
using a lock to make writing to and reading from the entire set of variables mutually exclusive activities.
Piggybacking on top of the volatile guard variable is a clever stunt—not one to be done casually. Subsequent updates to the program can break the aforementioned fragile conditions, removing the consistency guarantees afforded by the Java memory model. Should you choose to use this technique, document its invariants and requirements in the code clearly.
Yes. volatile, locks, etc., setup the happens-before relationship, but it affects all variables (in the new Java Memory Model (JMM) from Java SE 5/JDK 1.4). Kind of makes it useful for non-primitive volatiles...
does that second thread see the values written to a, b and c by the first thread, even though they are not themselves declared volatile? Or can it possibly see stale values?
You will get stale reads, b/c you can't ensure that the values of a, b, c are the ones set after reading of v. Using state machine (but you need CAS to change the state) is a way to tackle similar issues but it's beyond the scope of the discussion.
Perhaps this part is unclear, after writing to v and reading first from v, you'd get the right results (non-stale reads), the main issue is that if you do
if (v==STATE1){...proceed...}, there is no guarantee some other thread would not be modifying the state of a/b/c. In that case, there will be state reads.
If you modify the a/b/c+v once only you'd get the correct result.
Mastering concurrency and and lock-free structures is a really hard one. Doug Lea has a good book on and most talks/articles of Dr. Cliff Click are a wonderful wealth, if you need something to start digging in.
Yes, volatile write "happens-before" next volatile read on the same variable.
While #seh is right on about consistency problems with multiple variables, there are use cases that less consistency is required.
For example, a writer thread updates some state variables; a reader thread displays them promptly. There's not much relation among the variables, we only care about reading the new values promptly. We could make every state variable volatile. Or we could use only one volatile variable as visibility guard.
However, the saving is only on the paper, performance wise there's hardly any difference. In either version, every state variable must be "flushed" by the writer and "loaded" by the reader. No free lunch.

Categories