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