guava/src/com/google/common/collect/Multimaps.java
public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) {
    return Synchronized.multimap(multimap, null);
  }
public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) {
    return Synchronized.multimap(multimap, null);
  }
Returns a synchronized (thread-safe) multimap backed by the specified multimap. In order to
guarantee serial access, it is critical that <b>all</b> access to the backing multimap is
accomplished through the returned multimap.

<p>It is imperative that the user manually synchronize on the returned multimap when accessing
any of its collection views:

<pre>{@code
Multimap<K, V> multimap = Multimaps.synchronizedMultimap(
HashMultimap.<K, V>create());
...
Collection<V> values = multimap.get(key);  // Needn't be in synchronized block
...
synchronized (multimap) {  // Synchronizing on multimap, not values!
Iterator<V> i = values.iterator(); // Must be in synchronized block
while (i.hasNext()) {
foo(i.next());
}
}
}</pre>

<p>Failure to follow this advice may result in non-deterministic behavior.

<p>Note that the generated multimap's {@link Multimap#removeAll} and {@link
Multimap#replaceValues} methods return collections that aren't synchronized.

<p>The returned multimap will be serializable if the specified multimap is serializable.

@param multimap the multimap to be wrapped in a synchronized view
@return a synchronized view of the specified multimap