Java volatile reference vs. AtomicReference - java

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".

Related

Difference in memory model semantics between final and volatile fields in Java

From Java Concurrency In Practice:
When a field is declared volatile, the compiler and runtime are put on
notice that this variable is shared and that operations on it should
not be reordered with other memory operations. Volatile variables are
not cached in registers or in caches where they are hidden from other
processors, so a read of a volatile variable always returns the most
recent write by any thread.(p25)
And,
Final fields can't be modified(although the objects they refer to can
be modified if they are mutable), but they also have special semantics
under the Java Memory Model. It is the use of final fields that makes
possible the guarantee of initialization safety(see Section 3.5.2)
that lets immutable objects be freely accessed and shared without
synchronization.(p32)
Reciting an unsafe publication:
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n) // might be true for other threads.
}
}
The value of n, surprisingly might be seen stale by other threads. But final modifier would do the trick. Similar to volatile, isn't it? Are final fields intrinsically volatile? (a possible explanation why final volatile is not allowed)
No, final fields are not intrinsically volatile.
If they were, that would have been unnecessarily expensive, because in most cases you need to put a StoreLoad barrier after a volatile write.
This can be avoided for final fields, because you have an additional constraint that can help you - you know that final fields must be initialized by the time the corresponding class or instance object is fully initialized.
The specification can be somewhat hard to read (take a look at section 17.5 of the JLS), but keep in mind that, like the notorious JMM Causality section, the main point was to formally describe what would be the intuitive behavior for most people.
As for implementation, it usually requires 2 things:
Ensuring that final field stores, including stores down the chain if the field is a reference, cannot be reordered with stores outside of the constructor. This is often a no-op, even if you inline your constructor, if the underlying hardware architecture has a strong memory model (like x86).
Ensuring that the first final field load in a given thread cannot be reordered with the first load in that same thread of the corresponding reference to which the field belongs to. This is almost always a no-op, as all compilers and most hardware architectures honor load dependencies.
In the end, the much less expensive on most architectures LoadStore and StoreStore barriers should be enough for implementing final fields.
===
You can read more about how final fields should be implemented under the covers in:
Doug Lea's JMM Cookbook (see the Final Fields section)
Alexey Shipilev's awesome All Fields Are Final blog-post.
===
P.S. Unsafe publication is dangerous even in the presence of final fields. See here for some caveats.
Is it a possible reason private volatile is not allowed?
private volatile is allowed.
Do you mean final volatile? Yes, these modifiers are incompatible by their nature - final var, which value/reference cannot be changed, do not need additional volatile goodies (and associated overhead) because mutation of final field is impossible and reads across multiple threads are consistent
But JMM does provide initialisation volatile-style consistancy for final fields. AFAIK it was implemented in JSR 133 (included in Java SE 5.0). Before this JSR init reads could be inconsistent during data race (and return null or some intermediate value for example)
PS: I've found classic article which mentions your problem. Highly recommend it (and the second part)
volatile only has relevance to modifications of the variable itself, not the object it refers to. It makes no sense to have a final volatile field because final fields cannot be modified. Just declare the field final and it should be fine.

Why does JDK sourcecode take a `final` copy of `volatile` instances

I read the JDK's source code about ConcurrentHashMap.
But the following code confused me:
public boolean isEmpty() {
final Segment<K,V>[] segments = this.segments;
...
}
My question is:
"this.segments" is declared:
final Segment<K,V>[] segments;
So, here, in the beginning of the method, declared a same type reference, point to the same memory.
Why did the author write it like this? Why didn't they use this.segments directly? Is there some reason?
This is an idiom typical for lock-free code involving volatile variables. At the first line you read the volatile once and then work with it. In the meantime another thread can update the volatile, but you are only interested in the value you initially read.
Also, even when the member variable in question is not volatile but final, this idiom has to do with CPU caches as reading from a stack location is more cache-friendly than reading from a random heap location. There is also a higher chance that the local var will end up bound to a CPU register.
For this latter case there is actually some controversy, since the JIT compiler will usually take care of those concerns, but Doug Lea is one of the guys who sticks with it on general principle.
I guess it's for performance consideration, so that we only need retrieve field value once.
You can refer to a singleton idiom from effective java by Joshua Bloch
His singleton is here:
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized(this) {
result = field;
if (result == null)
field = result = computeFieldValue();
}
}
return result;
}
and he wrote:
This code may appear a bit convoluted. In particular, the need for the
local variable result may be unclear. What this variable does is to
ensure that field is read only once in the common case where it’s
already initialized. While not strictly necessary, this may improve
performance and is more elegant by the standards applied to low-level
concurrent programming. On my machine, the method above is about 25
percent faster than the obvious version without a local variable.
It may reduce byte code size - accessing a local variable is shorter in byte code than accessing an instance variable.
Runtime optimization overhead may be reduced too.
But none of these are significant. It's more about code style. If you feel comfortable with instance variables, by all means. Doug Lea probably feel more comfortable dealing with local variables.

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).

Equivalent of AtomicReference but without the volatile synchronization cost

What is the equivalent of:
AtomicReference<SomeClass> ref = new AtomicReference<SomeClass>( ... );
but without the synchronization cost. Note that I do want to wrap a reference inside another object.
I've looked at the classes extending the Reference abstract class but I'm a bit lost amongst all the choices.
I need something really simple, not weak nor phantom nor all the other references besides one. Which class should I use?
If you want a reference without thread safety you can use an array of one.
MyObject[] ref = { new MyObject() };
MyObject mo = ref[0];
ref[0] = n;
If you are simply trying to store a reference in an object. Can't you create a class with a field, considering the field would be a strong reference that should achieve what you want
You shouldn't create a StrongReference class (because it would be silly) but to demonstrate it
public class StrongReference{
Object refernece;
public void set(Object ref){
this.reference =ref;
}
public Object get(){
return this.reference;
}
}
Since Java 9 you can now use AtomicReference.setPlain() and AtomicReference.getPlain().
JavaDoc on setPlain:
"Sets the value to newValue, with memory semantics of setting as if the variable was declared non-volatile and non-final."
AtomicReference does not have the cost of synchronization in the sense of traditional synchronized sections. It is implemented as non-blocking, meaning that threads that wait to "acquire the lock" are not context-switched, which makes it very fast in practice. Probably for concurrently updating a single reference, you cannot find a faster method.
If you still want to use AtomicReference but don't want to incur the cost of the volatile write you can use lazySet
The write doesn't issue a memory barrier that a normal volatile write does, but the get still invokes a volatile load (which is relatively cheap)
AtomicReference<SomeClass> ref = new AtomicReference<SomeClass>();
ref.lazySet(someClass);
I think all you want is:
public class MyReference<T>{
T reference;
public void set(T ref){
this.reference =ref;
}
public T get(){
return this.reference;
}
}
You might consider adding delegating equals(), hashcode(), and toString().
To use java.util.concurrent.atomic.AtomicReference feels wrong to me too in order to share a reference of an object. Besides the "atomicity costs" AtomicReference is full of methods that are irrelevant for your use case and may raise wrong expectations to the user.
But I haven't encounter such an equivalent class in the JDK yet.
Here is a summary of your options - chose what fits best to you:
A self-written value container like the proposed StrongReference or MyReference from the other answers
MutableObject from Apache Commons Lang
Array with length == 1 or a List with size == 1
setPlain(V) and getPlain() in AtomicReference since Java 9
all provided classes extending Reference has some special functionality attached, from atomic CaS to allowing the referenced object to be collected event thoguh a reference still exists to the object
you can create your own StringReference as John Vint explained (or use a array with length==1) but there aren't that many uses for that though
There is no synchronization cost to AtomicReference. From the description of the java.util.concurrent.atomic package:
A small toolkit of classes that support lock-free thread-safe programming on single variables.
EDIT
Based on your comments to your original post, it seems that you used the term "synchronization cost" in a non-standard way to mean thread-local cache flushing in general. On most architectures, reading a volatile is nearly as cheap as reading a non-volatile value. Any update to a shared variable is going to require cache flushing of at least that variable (unless you are going to abolish thread-local caches entirely). There isn't anything cheaper (performance-wise) than the classes in java.util.concurrent.atomic.
If your value is immutable, java.util.Optional looks like a great option.

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