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).
Related
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.
As far as I know reference assignment is atomic in a 64 bit JVM.
Now, I assume the jvm doesn't use atomic pointers internally to model this, since otherwise there would be no need for Atomic References. So my questions are:
Is atomic reference assignment in the "specs" of java/Scala and guaranteed to happen or is it just a happy coincidence that it is that way most times ?
Is atomic reference assignment implied for any language that compiles to the JVM's bytecode (e.g. clojure, Groovy, JRuby, JPython...etc) ?
How can reference assignment be atomic without using an atomic pointer internally ?
First of all, reference assignment is atomic because the specification says so. Besides that, there is no obstacle for JVM implementors to fulfill this constraint, as 64 Bit references are usually only used on 64 Bit architectures, where atomic 64 Bit assignment comes for free.
Your main confusion stems from the assumption that the additional “Atomic References” feature means exactly that, due to its name. But the AtomicReference class offers far more, as it encapsulates a volatile reference, which has stronger memory visibility guarantees in a multi-threaded execution.
Having an atomic reference update does not necessarily imply that a thread reading the reference will also see consistent values regarding the fields of the object reachable through that reference. All it guarantees is that you will read either the null reference or a valid reference to an existing object that actually was stored by some thread. If you want more guarantees, you need constructs like synchronization, volatile references, or an AtomicReference.
AtomicReference also offers atomic update operations like compareAndSet or getAndSet. These are not possible with ordinary reference variables using built-in language constructs (but only with special classes like AtomicReferenceFieldUpdater or VarHandle).
Atomic reference assignment is in the specs.
Writes to and reads of references are always atomic, regardless of
whether they are implemented as 32 or 64 bit values.
Quoted from JSR-133: Java(TM) Memory Model and Thread Specification, section 12 Non-atomic Treatment of double and long, http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf.
As the other answer outlines, the Java Memory Model states that references read/writes are atomic.
But of course, that is the Java language memory model. On the other hand: no matter if we talk Java or Scala or Kotlin or ... in the end everything gets compiled into bytecode.
There are no special bytecode instructions for Java. Scala in the end uses the very same instructions.
Leading to: the properties of that memory model must be implemented inside the VM platform. Thus they must apply to other languages running on the platform as well.
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.
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.
Is there any difference between a volatile Object reference and AtomicReference in case I would just use get() and set()-methods from AtomicReference?
Short answer is: No.
From the java.util.concurrent.atomic package documentation. To quote:
The memory effects for accesses and updates of atomics generally follow the rules for volatiles:
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
By the way, that documentation is very good and everything is explained.
AtomicReference::lazySet is a newer (Java 6+) operation introduced that has semantics unachievable through volatile variables. See this post for more information.
No, there is not.
The additional power provided by AtomicReference is the compareAndSet() method and friends. If you do not need those methods, a volatile reference provides the same semantics as AtomicReference.set() and .get().
There are several differences and tradeoffs:
Using an AtomicReference get/set has the same JMM semantics as a volatile field(as the javadoc states), but the AtomicReference is a wrapper around a reference, so any access to the field involves a further pointer chase.
The memory footprint is multiplied (assuming a compressed OOPs environment, which is true for most VMs):
volatile ref = 4b
AtomicReference = 4b + 16b (12b object header + 4b ref field)
AtomicReference offers a richer API than a volatile reference. You can regain the API for the volatile reference by using an AtomicFieldUpdater, or with Java 9 a VarHandle. You can also reach straight for sun.misc.Unsafe if you like running with scissors. AtomicReference itself is implemented using Unsafe.
So, when is it good to choose one over the other:
Only need get/set? Stick with a volatile field, simplest solution and lowest overhead.
Need the extra functionality? If this is a performance(speed/memory overhead) sensitive part of your code make a choice between AtomicReference/AtomicFieldUpdater/Unsafe where you tend to pay in readability and risk for your performance gain. If this not a sensitive area just go for AtomicReference. Library writers typically use a mix of these methods depending on targeted JDKs, expected API restrictions, memory constraints and so on.
JDK source code is one of the best ways to answers confusions like this. If you look at the code in AtomicReference, it uses a volatie variable for object storage.
private volatile V value;
So, obviously if you are going to just use get() and set() on AtomicReference it is like using a volatile variable. But as other readers commented, AtomicReference provides additional CAS semantics. So, first decide if you want CAS semantics or not, and if you do only then use AtomicReference.
AtomicReference provides additional functionality which a plain volatile variable does not provide. As you have read the API Javadoc you will know this, but it also provides a lock which can be useful for some operations.
However, unless you need this additional functionality I suggest you use a plain volatile field.
Sometimes even if you only use gets and sets, AtomicReference might be a good choice:
Example with volatile:
private volatile Status status;
...
public setNewStatus(Status newStatus){
status = newStatus;
}
public void doSomethingConditionally() {
if(status.isOk()){
System.out.println("Status is ok: " + status); // here status might not be OK anymore because in the meantime some called setNewStatus(). setNewStatus should be synchronized
}
}
The implementation with AtomicReference would give you a copy-on-write synchronization for free.
private AtomicReference<Status> statusWrapper;
...
public void doSomethingConditionally() {
Status status = statusWrapper.get();
if(status.isOk()){
System.out.println("Status is ok: " + status); // here even if in the meantime some called setNewStatus() we're still referring to the old one
}
}
One might say that you could still could have a proper copy if you substituted:
Status status = statusWrapper.get();
with:
Status statusCopy = status;
However the second one is more likely to be removed by someone accidentally in the future during "code cleaning".