Well, that's still not particularly safe, b/c it depends a lot of the underlying implementation of the HashMultimap.
You might take a look at the following blog post for a discussion: http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html
For this type of thing, a common pattern is to load a "most recent version" into a volatile variable and have your readers read immutable versions through that. This is how CopyOnWriteArrayList
is implemented.
Something like ...
class Collector { private volatile HashMultimap values = HashMultimap.create(); public add(String k, String v) { HashMultimap t = HashMultimap.create(values); t.put(k,v); this.values = t; // this invokes a memory barrier } public Set<String> get(String k) { values.get(k); // this volatile read is memory barrier }}
However, both your and my solution still have a bit of a problem -- we are both returning mutable views on the underlying data structure. I might change the HashMultimap
to an ImmutableMultimap
to fix the mutability issue. Beware also that callers retain a reference to the full internal map (not just the returned Set) as a side effect of things being a view.
Creating a new copy can seem somewhat wasteful, but I suspect that if you have only one thread writing, then you have an understanding of the rate of change and can decide if that's reasonable or not. For example, f you wanted to return Set<String>
instances which update dynamically as things change then the solution based on map maker doesn't seem heavy handed.