Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The setPoint() method does not currently need to be synchronized because it operates atomically on immutable data, that is, on an instance of ImmutablePoint. However, remember that the volatile keyword does not protect against TOCTOU race conditions. A routine that checked the current value of ipoint and subsequently set it would require additional locking to prevent the TOCTOU race condition. Such locking would render the volatile keyword unnecessary.

Noncompliant Code Example (partial initialization)

Thread-safe classes (which may not be strictly immutable), such as Container in this noncompliant code example, must declare fields as final or volatile, or synchronize all accesses of the field (see CON09-J. Synchronize access to shared references). In the absence of synchronization, non-final, non-volatile fields may be observed by other threads before the sub-objects' initialization has concluded.

This noncompliant code example fails to declare the map field as volatile or final. Consequently, a thread that invokes the get() method may observe the value of the map field before initialization has concluded.

Code Block
bgColor#FFcccc

public class Container<K,V> {
  Map<K,V> map;

  public synchronized void initialize() {
    if (map == null) {
      map = new HashMap<K,V>();	         
      // Fill some useful values into HashMap
    }
  }

  public V get(Object k) {
    if (map != null) {
      return map.get(k);
    } else {
      return null;
    }
  }
}

Compliant Solution (proper initialization)

This compliant solution declares the map field as volatile to ensure other threads see an up-to-date HashMap reference.

Code Block
bgColor#ccccff

public class Container<K,V> {
  volatile Map<K,V> map;

  public synchronized void initialize() {
    if (map == null) {
      map = new HashMap<K,V>();	         
      // Fill some useful values into HashMap
    }
  }

  public V get(Object k) {
    if (map != null) {
      return map.get(k);
    } else {
      return null;
    }
  }
}

Wiki Markup
Alternative solutions to using {{volatile}} for safe publication are described in [CON26-J. Do not publish partially-constructed objects]. These alternative solutions are recommended if the values of the {{map}} can be mutated after initialization because the use of {{volatile}} only guarantees "one time safe publication" \[[Goetz 06|AA. Java References#Goetz 06]\], that is the reference is made visible only after initialization. There is no guarantee that any future updates to the map's contents will be visible immediately (see [CON11-J. Do not assume that declaring an object volatile guarantees visibility of its members] for more information). 

Risk Assessment

Failing to use volatile to guarantee visibility of shared values across multiple thread and prevent reordering of accesses can result in unpredictable control flow.

...