You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Noncompliant Code Example (collection view)

This noncompliant code example incorrectly synchronizes on the set view of the synchronized map (map) instead of the collection object.

// map has package-private accessibility
final Map<Integer, String> map = Collections.synchronizedMap(new HashMap<Integer, String>());
private final Set<Integer> set = map.keySet();

public void doSomething() {
  synchronized(set) {  // Incorrectly synchronizes on set
    for (Integer k : set) { 
      // ...
    }
  }
}

When using synchronization wrappers, the synchronization object should be the Collection object. The synchronization is necessary to enforce atomicity ([CON07-J. Do not assume that a grouping of calls to independently atomic methods is atomic]). This noncompliant code example demonstrates inappropriate synchronization resulting from locking on a Collection view instead of the Collection object itself [[Tutorials 08]].

The java.util.Collections interface's documentation [[API 06]] warns about the consequences of following this practice:

It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views... Failure to follow this advice may result in non-deterministic behavior.

Compliant Solution (collection lock object)

This compliant solution synchronizes on the Collection object map instead of the Collection view set.

// map has package-private accessibility
final Map<Integer, String> map = Collections.synchronizedMap(new HashMap<Integer, String>());
private final Set<Integer> set = map.keySet();

public void doSomething() {
  synchronized(map) {  // Synchronize on map, not set
    for (Integer k : set) { 
      // ...
    }
  }
}
  • No labels