Search code examples
javamultithreadingvolatile

Mixing volatile and non-volatile


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();
  }

  …
}

Solution

  • 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