This question is somewhat continuation and expansion of this one, as I think perfect question: How does assigning to a local variable help here?
This question based on Item 71
of Effective Java
, where it is suggested to speed up performance by introducing local variable in purpose of volatile
field access:
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
So, my question is more common:
should we always access to volatile
fields through assigning their values to local variables? (in order to archive best performance).
I.e. some idiom:
we have some volatile
field, call it just volatileField
;
if we want to read its value in multi-thread method, we should:
localVolatileVariable
localVolatileVariable = volatileField
read value from this local copy, e.g.:
if (localVolatileVariable != null) { ... }
You must assign volatile variables to local fields if you plan on doing any sort of multi-step logic (assuming of course, that the field is mutable).
for instance:
volatile String _field;
public int getFieldLength() {
String tmp = _field;
if(tmp != null) {
return tmp.length();
}
return 0;
}
if you did not use a local copy of _field
, then the value could change between the "if" test and the "length()" method call, potentially resulting in an NPE.
this is besides the obvious benefit of a speed improvement by not doing more than one volatile read.
There are two sides of a coin.
On the one hand assignment to a volatile works like a memory barrier and it's very unlikely that JIT will reorder assignment with computeFieldValue invocation.
On the other hand in theory this code breaks JMM. Because for some reasons some JVM is allowed to reorder computeFieldValue with assignment and you see partially initialized object. This is possible as long as variable read is not order with variable write.
field = result = computeFieldValue();
does not happen before
if (result == null) { // First check (no locking)
As long as java code supposed to be "write once run everywhere" DCL is a bad practice and should be avoided. This code is broken and is not a point of consideration.
If you have multiple reads of a volatile variable in a method, by assigning it to a local variable first you minimize such reads, which are more expensive. But I don't think, that you get a performance boost. This is likely to be a theoretical improvement. Such optimization should be left to JIT and is not a point of developer's considerations. I agree with this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With