3

My question applies to a field which is initially null, then is initialised to a non-null value, and then doesn’t change anymore.

As this field needs to be available as soon as possible to all threads, I need to use volatile.

But if I want to avoid the overhead of volatile access whenever possible (i.e. when a non-volatile field is enough), would the following code make any sense?

public class User {
  private String nonVolatileName;
  private volatile String volatileName;

  public String getName() {
    final String name = nonVolatileName;
    return name != null ? name : volatileName;
  }

  private void initName() {
    volatileName = nonVolatileName = expensiveComputation();
  }

  …
}
Julien Royer
  • 1,419
  • 1
  • 14
  • 27

1 Answers1

3

Yeah, the code will work because "A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field." [1]

return name != null ? name : volatileName;

so as long as name == null you will be forcing a read from a volatile variable until it is not null (i.e. expensiveComputation has completed) which given the happen before semantics ensures that you see the non null value in nonVolatileName from then onward. See also here [2]

Have fun explaining this to your colleagues though

[1] https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5-320

[2] Volatile variables and other variables

David Soroko
  • 8,521
  • 2
  • 39
  • 51
  • Thank you for your comprehensive answer! is there a simpler way of doing that in Java? – Julien Royer Nov 26 '19 at 09:01
  • 2
    It is rather ugly isn't it? Do you really have a use case where using/not using `volatile` this way makes a tangible difference? – David Soroko Nov 26 '19 at 09:40
  • Well, intellectually it seems that it can make a difference because this field is accessed very frequently; but as suggested by Suma I need to run a benchmark in order to prove it (or not). – Julien Royer Nov 26 '19 at 10:02
  • 1
    I you have time, please, post the benchmark result here as a comment, I am curious to learn what will you see. – Suma Nov 26 '19 at 12:34
  • @Suma the benchmark is here: https://github.com/julienroyer/mixing-volatile-and-non-volatile - it might be wrong as I am an absolute beginner with benchmark tools. The result I got (see the results directory) suggests that the difference is not noticeable. – Julien Royer Dec 12 '19 at 16:58