Why should I use 'Volatile' instead of just always using 'Atomic'? [duplicate] - java

This question already has answers here:
Volatile Vs Atomic [duplicate]
(6 answers)
Closed last year.
I know the differences between both in terms of visibility and ensuring atomic access and atomic operations. But I was wondering, if for example I only needed to use Volatile, and Atomic wasn't necessary, is there an advantage (maybe memory or efficiency wise) to using just Volatile? Or can I just use Atomic instead?

The get() and set(...) methods of a Java AtomicWhatever object have exactly the same semantics as assignments to, and reads from, a volatile variable. So in effect, "Atomic" is a superset of "volatile."
The semantics are simple: If one thread assigns a volatile variable or, if it set(...)s an AtomicXxxxxx object, then whatever else it did before that assignment is guaranteed to be visible to some other thread after the other thread subsequently reads the same variable or, after it subsequently get()s from the same object.
volatile was in the language from the beginning. Atomics are newer. Some programmers will tell you that because atomics effectively are "volatile," that we don't need the volatile keyword anymore, and you should not use it. That's a matter of opinion, but if you're working on a team with other developers, it's best to use the same style and the same patterns that everybody else on the team uses.

Related

Can using volatile with "AtomicInteger" guarantees thread safety? [duplicate]

This question already has answers here:
What is the difference between atomic / volatile / synchronized?
(7 answers)
Closed 3 years ago.
Suppose I have
private volatile AtomicInteger atomInt = new AtomicInteger(3);
and in methods my usage is atomInt.incrementAndGet().
Since I am using AtomicInteger, it will avoid "thread interference". And then I am using volatile, so it will guarantee the consistent view of the variable across all threads. Does it mean that I have got complete thread safety or still there are chances of "memory consistency issues"?
I got confused because of usage of "reduce" in tutorial, so it suggests me that there are still chances but I cannot think of it:
Using volatile variables reduces the risk of memory consistency
errors, because any write to a volatile variable establishes a
happens-before relationship with subsequent reads of that same
variable.
And then I am using volatile, so it will guarantee the consistent view of the variable across all threads.
Thread-safety is already guaranteed by atomic variables. volatile is redundant if you won't reassign the variable. You can replace volatile with final here:
private final AtomicInteger atomInt = new AtomicInteger(3);
Does it mean that I have got complete thread safety or still there are chances of "memory consistency issues"?
At this moment, it's absolutely thread-safe. No "memory consistency issues" might happen with the variable. But using proper thread-safe components doesn't mean that the whole class/program is thread-safe. Problems might take place if interactions between them are incorrect.
Using volatile variables reduces the risk of memory consistency errors ...
volatile variables can only guarantee visibility. They don't guarantee atomicity.
As Brian Goetz writes (emphasis mine):
volatile variables are convenient, but they have limitations. The most common use for volatile variables is as a completion, interruption, or status flag. Volatile variables can be used for other kinds of state information, but more care is required when attempting this. For example, the semantics of volatile are not strong enough to make the increment operation (count++) atomic, unless you can guarantee that the variable is written only from a single thread.
You can use volatile variables only when all the following criteria are met:
Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
The variable does not participate in invariants with other state variables;
Locking is not required for any other reason while the variable is being accessed.
From the docs of the java.util.concurrent.atomic package:
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
Volatile does mean that changes to the variable will be visible. But in this case you shouldn’t be changing the reference held by the variable.
It seems very odd that you’d want to make a reference to an Atomic object volatile. The whole point of the atomicinteger class is to provide a way to access and change an integer value safely. The only reason to make some variable volatile is because you intend to overwrite its value. Why overwrite the reference to the AtomicInteger when you can use its instance methods to update its value?
That’s why you are getting advice to make this variable final instead of volatile. Making the variable final nails down the reference so it can’t change, while making sure the reference contained by that variable is visible. The atomicInteger manages its own state in a threadsafe way so you shouldn’t have to overwrite the reference to it.
So it’s not exactly correct to say volatile is redundant here. But it is doing something that typically shouldn’t have to be done. Use volatile when you have to change the value contained in the variable. Use final when you shouldn’t be changing the value contained in the variable.

Is volatile keyword of any use if I run the application in single core machine? [duplicate]

This question already has answers here:
Volatile keyword in multicore vs single processor?
(4 answers)
Closed 5 years ago.
I have recently getting myself familiarized with volatile keyword and I see that not reading from main memory directly can result in inconsistency and the so-called visibility problem.
I believe the CPU cache is not specific to any thread. So I was wondering if the volatile keyword will be of any use in singlecore processor?
Hardware-level concurrency is obviously an important part of the motivation for the spec, but the spec is quite clear that the requirements apply to the system as a whole; so, for example, the JVM's "just-in-time" (JIT) compiler can legitimately optimize the equivalent of
while (this.var) {
... code that provably never modifies var ...
}
to the equivalent of
if (this.var) {
while (true) {
... code that provably never modifies var ...
}
}
if var is not volatile.
Well, having a single or multi processors(cores) certainly has impact on the ability of the overall program to run parallely effectively, you still can create multiple Threads and they will have their own cache and volatile keyword will still function as it is intended to - The JLS doesn't specify a processor dependent behavior change for the keyword.
Note that the only thing different is being effectively parallel which is not a determinant of the behavior of the keyword.

using volatile keyword in java4 and java5

what is the difference in using volatile keyword in java4 and java5 onwards?
and related to that,
Read/write operations on non-atomic variables(long/double) are atomic when they are
declared as volatile.
Is this also true for java4 or it is valid from java5 onwards???
Yes there is a difference.
Up to Java 4 volatile could be re-ordered by compiler with respect to any previous read or write, leading to subtle concurrency bugs e.g. making it impossible to implement a double check locking (very common idiom for a Singleton).
This is fixed in Java 5.0 which extends the semantics for volatile which cannot be reordered with respect to any following read or write anymore and introduces a new memory model. You can read this Double Checked Locking for example reference
This site gives a good explanation of the differences: http://www.javamex.com/tutorials/synchronization_volatile.shtml
They also give an explanation of the behavior of volatile in Java 5 on a separate page: http://www.javamex.com/tutorials/synchronization_volatile_java_5.shtml
People have provided good points and references responding to my question answering first part.
Going specific to the second part of question, this i read at some forum:
A volatile declared long is atomic (pre-Java 5 also) in the sense that
it guarantees (for all JVM implementations) a read or write go
directly to main memory instead of two 32-bit registers.
And
Pre-Java 5, volatile was supposed to provide such guarantees for long
and double. However things did not work out this way in practice, and
implementations frequently violated this guarantee. As I recall the
issue seemed to get fixed around JDK 1.4, but as they were still
working on the whole memory model thing, they didn't really make any
clear announcements about it until JDK 5, when the new rules were
announced, and memory guarantees actually meant something.
And this is from Java Language Specification,Second Edition:
17.4 Nonatomic Treatment of double and long
The load, store, read, and write actions on volatile variables are atomic,
even if the type of the variable is double or long.
What is the difference in using volatile keyword in java4 and java5 onwards?
JMM before JDK5 is broken and using volatile for JDK4 may not provide the intended result. For more check this:
http://www.ibm.com/developerworks/library/j-jtp02244/
Read/write operations on non-atomic variables(long/double) are atomic when they are declared as volatile.
Read/Write for long/double happen as two separate 32-bit operations. For two threads it is possible that one thread has read higher 32-bits and other one has read lower 32-bits of a long/double variable. In short read/write on long is not atomic operation unlike other primitives.
Using volatile for long/double is supposed to provide such guarantee as the instructions for volatile are not re-ordered for volatile read/write by compiler and volatile also provides visibility guarantee. But again it may not work for JDK 4 or before.

java and C++11 volatile

I'd like to port some piece of code from Java to C++11 and I'm a bit confused with volatile keyword.
I'm not familiar with Java language and I don't get what a volatile variable is. It guarantees that every thread has access to the up to date value of variable - it is the C++ volatile behaviour. But it is usually used to synchronize - are all actions performed on volatile variable atomic?
So I think thath the C++11 good replacement for Java volatile will be std::atomic. Or I'm totally wrong, cause I missed some additional Java volatile features?
Yes, they would be a good match, there is a good article on this at Dr Dobbs.
In a nutshell, ordered atomic variables are safe to read and write on
multiple threads at the same time without doing any explicit locking
because they provide two guarantees: their reads and writes are
guaranteed to be executed in the order they appear in your program's
source code; and each read or write is guaranteed to be atomic,
all-or-nothing.
Java provides this type of variable as volatile, C++ as std::atomic.
This page has a pretty nice explanation on Java's volatile keyword: http://www.javamex.com/tutorials/synchronization_volatile.shtml. It looks to me that C++11 std::atomic<> on primitive types (e.g., integers) indeed is a good replacement. Note that std::atomic<> provides support for read-modify-write operations (e.g., compare_exchange_strong and fetch_add).

Method call and atomicity

I have a method with a single atomic operation, like this one
int value;
public void setValue(int value) {
this.value = value;
}
then I call it in obvious way, like
foo.setValue(10);
The question is: would it be atomic operation? If no, what atomic operations will be executed? How I can test this at my computer (if I can)?
Yes, the
this.value = value;
operation is atomic. See the Java Language Specification: Threads and Locks.
Note though that threads are allowed to cache their own values of non-volatile variables, so it is not guaranteed that a successive get-operation would yield the last set value.
To get rid of these kind of data races you need to synchronize the access to the variable somehow. This can be done by
making the method synchronized,
by letting the variable be volatile or,
use AtomicInteger from the java.util.concurrent package. (preferred way imo)
It should also be noted that the operation would not be atomic if you changed from int to long or double. Here is a relevant section from the JLS:
17.4 Non-atomic Treatment of double and long
If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write actions they are treated as if they were two variables of 32 bits each: wherever the rules require one of these actions, two such actions are performed, one for each 32-bit half.
Some useful links:
Wikipedia article on the Java Memory Model
Java Language Specification, Interaction with the Memory Model
It is atomic, because it is just a primitive 32 bit value.
Hence when you read it, there is a guarantee that you will see a value set by one of the threads, but you won't know which one it was.
If it was a long, you wouldn't have the same guarantee, although in practice most VM implementations do treat long writes as atomic operations.
This is what the JLS has to say on the issue:
VM implementors are encouraged to avoid splitting their 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.
But with ints you are safe, question is, is this very weak guarantee enough for you? More often than not, the answer is a no.
First of all, assignment to all primitive types (except 64-bit ones) in Java is atomic according to the Java specification. But for instance auto-increment isn't thread-safe, no matter which type you use.
But the real problem with this code is not atomicity, but visibility. If two threads are modifying the value, they might not see the changes made by each other. Use the volatile keyword or, even better, AtomicInteger to guarantee correct synchronization and visibility.
Please note that synchronized keyword also guarantees visibility, which means if some modification happens inside synchronnized block, it is guaranteed that it will be visible by other threads.

Categories

Resources