Related
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.
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.
As Integer class is also immutable class and we know that immutable class is thread-safe what is the need of Atomic Integer.
I am confused .
Is it the reason that reads and write of immutable objects need not be atomic whereas read and write of atomic integer is atomic .
That means atomic classes are also thread-safe.
AtomicInteger is used in multithreaded environments when you need to make sure that only one thread can update an int variable. The advantage is that no external synchronization is requried since the operations which modify it's value are executed in a thread-safe way.
Consider the followind code:
private int count;
public int updateCounter() {
return ++count;
}
If multiple threads would call the updateCounter method, it's possible that some of them would receive the same value. The reason it that the ++count operation isn't atomical since isn't only one operation, but made from three operations: read count, add 1 to it's value and write it back to it. Multiple calling threads could see the variable as unmodified to it's latest value.
The above code should be replaced with this:
private AtomicInteger count = new AtomicInteger(0);
public int updateCounter() {
return count.incrementAndGet();
}
The incrementAndGet method is guaranteed to atomically increment the stored value and return it's value without using any external synchonization.
If your value never changes, you don't have to use the AtomicInteger, it's enought to use int.
AtomicInteger is thread safe (in fact, all classes from java.util.concurrent.atomic package are thread safe), while normal integers are NOT threadsafe.
You would require 'synchronized' & 'volatile' keywords, when you are using an 'Integer' variable in multi-threaded environment (to make it thread safe) where as with atomic integers you don't need 'synchronized' & 'volatile' keywords as atomic integers take care of thread safety.
Also, I would recommend the below helpful tutorial on the same subject:
http://tutorials.jenkov.com/java-concurrency/compare-and-swap.html
Please refer below oracle doc for more information on 'atomic' package:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html
While immutable objects are thread-safe by definition, mutable objects can be thread safe too.
That is precisely the purpose of the Atomic... classes (AtomicInteger, AtomicBoolean, and so on).
The various ...get... and ...set... methods allow thread-safe access and mutation of the object.
Not surprisingly, the class is declared in the java.util.concurrent package.
You only have to browse the API for the java.util.concurrent.atomic package:
A small toolkit of classes that support lock-free thread-safe programming on single variables.
Consider a variable
int myInt = 3;
AtomicInteger relates to myInt.
Integer relates to 3.
in other words, your variable is mutable and can change it's value. While the value 3 is an integer literal, a constant, an immutable expression.
Integers are object representations of literals and are therefore immutable, you can basically only read them.
AtomicIntegers are containers for those values. You can read and set them. Same as asigning a value to variable. But different to changing the value of int variable, operations on an AtomicInteger are atomic.
For example this is not atomic
if(myInt == 3) {
myInt++;
}
This is atomic
AtomicInteger myInt = new AtomicInteger(3);
//atomic
myInt.compareAndSet(3, 4);
I think the main difference between AtomicInteger and normal immutable Integer will come into the picture, once we understand why even immutable Integers are not thread-safe.
Let's see with an example.
Suppose, we have a value of int count = 5, which is being shared by two different threads named T1 and T2 with both reading and writing at the same time.
We know that, if there is any value being reassigned into an immutable object, the old object remains at the pool and the new one takes over.
Now, when T1 and T2 are updating their values into count variable, Java might take this value into some cache and will do the set operations there and we won't know when JVM will write the updated value into main memory, so there might be a possibility that one of the threads may be updating the value into a totally stale value.
This brings us to the volatile keyword.
Volatile - This keyword ensures that all the I/O operations on any variable will take place on the main memory so that all the threads are working with the most updated value.
Consider, if 1 Thread is writing and all other threads are reading then, volatile will solve our problem, but if all the threads are reading and writing on the same variable at the same time, then we need synchronizing to ensure thread-safety.
Volatile keyword does not ensure thread-safety.
Now, coming to why AtomicIntegers. Even if are using syncrhonized keyword to ensure thread-safety, the actual update operation of count variable will be a three step process.
get updated value of count variable
increment the value by 1
set the value to count variable
This is why it takes a slightly longer time to update any value for normal Integers to update values once the thread safety is taken into consideration.
**AtomicIntegers solve this problem furthermore of thread safety and also faster updates by an optimized lock-free algorithm called Compare-And-Swap (CAS method).
They perform all the update operations atomically as a single-step process. **
This question already has answers here:
What is the difference between atomic / volatile / synchronized?
(7 answers)
Closed 9 years ago.
I read somewhere below line.
Java volatile keyword doesn't means atomic, its common misconception
that after declaring volatile, ++ operation will be atomic, to make
the operation atomic you still need to ensure exclusive access using
synchronized method or block in Java.
So what will happen if two threads attack a volatile primitive variable at same time?
Does this mean that whosoever takes lock on it, that will be setting its value first. And if in meantime, some other thread comes up and read old value while first thread was changing its value, then doesn't new thread will read its old value?
What is the difference between Atomic and volatile keyword?
The effect of the volatile keyword is approximately that each individual read or write operation on that variable is made atomically visible to all threads.
Notably, however, an operation that requires more than one read/write -- such as i++, which is equivalent to i = i + 1, which does one read and one write -- is not atomic, since another thread may write to i between the read and the write.
The Atomic classes, like AtomicInteger and AtomicReference, provide a wider variety of operations atomically, specifically including increment for AtomicInteger.
Volatile and Atomic are two different concepts. Volatile ensures, that a certain, expected (memory) state is true across different threads, while Atomics ensure that operation on variables are performed atomically.
Take the following example of two threads in Java:
Thread A:
value = 1;
done = true;
Thread B:
if (done)
System.out.println(value);
Starting with value = 0 and done = false the rule of threading tells us, that it is undefined whether or not Thread B will print value. Furthermore value is undefined at that point as well! To explain this you need to know a bit about Java memory management (which can be complex), in short: Threads may create local copies of variables, and the JVM can reorder code to optimize it, therefore there is no guarantee that the above code is run in exactly that order. Setting done to true and then setting value to 1 could be a possible outcome of the JIT optimizations.
volatile only ensures, that at the moment of access of such a variable, the new value will be immediately visible to all other threads and the order of execution ensures, that the code is at the state you would expect it to be. So in case of the code above, defining done as volatile will ensure that whenever Thread B checks the variable, it is either false, or true, and if it is true, then value has been set to 1 as well.
As a side-effect of volatile, the value of such a variable is set thread-wide atomically (at a very minor cost of execution speed). This is however only important on 32-bit systems that i.E. use long (64-bit) variables (or similar), in most other cases setting/reading a variable is atomic anyways. But there is an important difference between an atomic access and an atomic operation. Volatile only ensures that the access is atomically, while Atomics ensure that the operation is atomically.
Take the following example:
i = i + 1;
No matter how you define i, a different Thread reading the value just when the above line is executed might get i, or i + 1, because the operation is not atomically. If the other thread sets i to a different value, in worst case i could be set back to whatever it was before by thread A, because it was just in the middle of calculating i + 1 based on the old value, and then set i again to that old value + 1. Explanation:
Assume i = 0
Thread A reads i, calculates i+1, which is 1
Thread B sets i to 1000 and returns
Thread A now sets i to the result of the operation, which is i = 1
Atomics like AtomicInteger ensure, that such operations happen atomically. So the above issue cannot happen, i would either be 1000 or 1001 once both threads are finished.
There are two important concepts in multithreading environment:
atomicity
visibility
The volatile keyword eradicates visibility problems, but it does not deal with atomicity. volatile will prevent the compiler from reordering instructions which involve a write and a subsequent read of a volatile variable; e.g. k++.
Here, k++ is not a single machine instruction, but three:
copy the value to a register;
increment the value;
place it back.
So, even if you declare a variable as volatile, this will not make this operation atomic; this means another thread can see a intermediate result which is a stale or unwanted value for the other thread.
On the other hand, AtomicInteger, AtomicReference are based on the Compare and swap instruction. CAS has three operands: a memory location V on which to operate, the expected old value A, and the new value B. CAS atomically updates V to the new value B, but only if the value in V matches the expected old value A; otherwise, it does nothing. In either case, it returns the value currently in V. The compareAndSet() methods of AtomicInteger and AtomicReference take advantage of this functionality, if it is supported by the underlying processor; if it is not, then the JVM implements it via spin lock.
As Trying as indicated, volatile deals only with visibility.
Consider this snippet in a concurrent environment:
boolean isStopped = false;
:
:
while (!isStopped) {
// do some kind of work
}
The idea here is that some thread could change the value of isStopped from false to true in order to indicate to the subsequent loop that it is time to stop looping.
Intuitively, there is no problem. Logically if another thread makes isStopped equal to true, then the loop must terminate. The reality is that the loop will likely never terminate even if another thread makes isStopped equal to true.
The reason for this is not intuitive, but consider that modern processors have multiple cores and that each core has multiple registers and multiple levels of cache memory that are not accessible to other processors. In other words, values that are cached in one processor's local memory are not visisble to threads executing on a different processor. Herein lies one of the central problems with concurrency: visibility.
The Java Memory Model makes no guarantees whatsoever about when changes that are made to a variable in one thread may become visible to other threads. In order to guarantee that updates are visisble as soon as they are made, you must synchronize.
The volatile keyword is a weak form of synchronization. While it does nothing for mutual exclusion or atomicity, it does provide a guarantee that changes made to a variable in one thread will become visible to other threads as soon as it is made. Because individual reads and writes to variables that are not 8-bytes are atomic in Java, declaring variables volatile provides an easy mechanism for providing visibility in situations where there are no other atomicity or mutual exclusion requirements.
The volatile keyword is used:
to make non atomic 64-bit operations atomic: long and double. (all other, primitive accesses are already guaranteed to be atomic!)
to make variable updates guaranteed to be seen by other threads + visibility effects: after writing to a volatile variable, all the variables that where visible before writing that variable become visible to another thread after reading the same volatile variable (happen-before ordering).
The java.util.concurrent.atomic.* classes are, according to the java docs:
A small toolkit of classes that support lock-free thread-safe
programming on single variables. In essence, the classes in this
package extend the notion of volatile values, fields, and array
elements to those that also provide an atomic conditional update
operation of the form:
boolean compareAndSet(expectedValue, updateValue);
The atomic classes are built around the atomic compareAndSet(...) function that maps to an atomic CPU instruction. The atomic classes introduce the happen-before ordering as the volatile variables do. (with one exception: weakCompareAndSet(...)).
From the java docs:
When a thread sees an update to an atomic variable caused by a
weakCompareAndSet, it does not necessarily see updates to any other
variables that occurred before the weakCompareAndSet.
To your question:
Does this mean that whosoever takes lock on it, that will be setting
its value first. And in if meantime, some other thread comes up and
read old value while first thread was changing its value, then doesn't
new thread will read its old value?
You don't lock anything, what you are describing is a typical race condition that will happen eventually if threads access shared data without proper synchronization. As already mentioned declaring a variable volatile in this case will only ensure that other threads will see the change of the variable (the value will not be cached in a register of some cache that is only seen by one thread).
What is the difference between AtomicInteger and volatile int?
AtomicInteger provides atomic operations on an int with proper synchronization (eg. incrementAndGet(), getAndAdd(...), ...), volatile int will just ensure the visibility of the int to other threads.
So what will happen if two threads attack a volatile primitive variable at same time?
Usually each one can increment the value. However sometime, both will update the value at the same time and instead of incrementing by 2 total, both thread increment by 1 and only 1 is added.
Does this mean that whosoever takes lock on it, that will be setting its value first.
There is no lock. That is what synchronized is for.
And in if meantime, some other thread comes up and read old value while first thread was changing its value, then doesn't new thread will read its old value?
Yes,
What is the difference between Atomic and volatile keyword?
AtomicXxxx wraps a volatile so they are basically same, the difference is that it provides higher level operations such as CompareAndSwap which is used to implement increment.
AtomicXxxx also supports lazySet. This is like a volatile set, but doesn't stall the pipeline waiting for the write to complete. It can mean that if you read a value you just write you might see the old value, but you shouldn't be doing that anyway. The difference is that setting a volatile takes about 5 ns, bit lazySet takes about 0.5 ns.
In Concurrency in Practice, it says you can use volatile variables if
Writes to the variable do not depend on its current value.
So, if you have a shared, mutable variable a, and all threads ever do to it is go a++ (they don't get the value, they just ++).
Then according to the quote, you should be able to make it volatile even though a++ is not atomic, correct?
No, using ++ on a volatile variable is not threadsafe, because
a++
is equivalent to:
int temp = a;
temp = temp + 1;
a = temp;
So the write back to a may happen after another thread has modified a since your thread read it, so a++, even if a is volatile, is not threadsafe.
You can use AtomicInteger, which implements threadsafe atomic incrementation.
a++ reads the value of a, since it's equivalent to
read a
increment the read value
assign the new value to a
So no, you can't safely use a volatile variable in this case.
- Volatile does the following things:
A field marked volatile, will have its value written to the memory immediately, and during retiring, its value is read from memory.
Prevents caching of value in Thread.
Eg:
a++ can be interpreted as following:
- Reading of the value of memory location named a.
- Incrementing the value.
- Writing the newly incremented value to memory location named a.
Now the whole above process is not Thread-Safe, and ++ (Increment operator) in Java is not an Atomic Statement.
- Better use synchronized keyword or if you don't like using it, go with AtomicInteger Class.
a++ is not atomic, it is equivalent to
retrieving a
adding 1
storing the result back into a
Thus, you can still "miss updates", if another thread gets in the way - volatile is not designed to prevent that, that's what "synchronised blocks" and "locks" are for.
The fact a is volatile only affects its visibility amongst threads, as a is not stored in the local cache, so different threads (running on different cores or processors) can immediately "see" its new value.