3

The problem: I have a ViewModel base class that has a HashMap to store the ViewModel's property values. However I'm encountering an intermittent bug where a read from this collection (on a seperate thread) is returning null directly after an item was added.

private HashMap<String, Serializable> _propertyValues = new HashMap<String, Serializable>();

An Example: I want to fetch user information when a user id is provided to the ViewModel.

ViewModel wires up to PropertyChanged for UserID. The property changed handler creates a background thread to pull the values. The background thread reads the UserID and then fetches from the server.

What we're seeing is that in some rare cases the background thread is reading null from the property hashmap (thread 2), directly after the value was provided (thread 1).

My Thoughts: I suspect this to be due to data visibility and the absence of a thread safe collection. When reviewing thread safe options I came across:

  1. Hashtable - Seems the community considers this out dated and discourages its use.
  2. ConcurrentHashMap - Seems like I could still run into my issue due to this lacking reliable synchronization
  3. Collections.synchronizedMap(map) - Seems particular in how you use it, not sure if it has benefits over Hashtable

At this time I feel like Hashtable is what I'll want, but could use confirmation. :)

Use Cases:

  1. 100ish reads all at once, every minute or so.
  2. Frequent writes from the UI thread
  3. Periodic reads from background threads that need accurate values. Background thread read, right after a UI thread write.

Thanks, Trey

yshavit
  • 42,327
  • 7
  • 87
  • 124
Trey
  • 263
  • 3
  • 5
  • You could also use locks so that other processes cannot access information until write locks are given up. – thatidiotguy Jan 24 '14 at 20:48
  • 1
    Locks are probably your only option here. What appears to be happening in your case is you *assume* the value has been written, but the read thread actually gets called before the write thread, and hence the values is null. You need a lock to ensure the write thread has completed before the read thread accesses the value. – Jeshurun Jan 24 '14 at 20:53
  • What do you mean by "particular in how you use it"? The advantage of `synchronizedMap(new HashMap())` is that `HashMap` has evolved over the past decade whereas `Hashtable` hasn't. – Marko Topolnik Jan 24 '14 at 20:54
  • Your other option might be using a `Executors.newSingleThreadExecutor()` like a `Queue`. This way, only one thread executes at a time, and if the read thread is submitted after the write thread, you can guarantee the read thread will have completed. It might cause a degradation in performance though. – Jeshurun Jan 24 '14 at 20:56
  • @MarkoTopolnik I've heard mostly subjective comments such as ["if used properly"](http://stackoverflow.com/questions/510632/whats-the-difference-between-concurrenthashmap-and-collections-synchronizedmap) when this is discussed. Nothing concrete. – Trey Jan 24 '14 at 21:17
  • 2
    Two "improper" ways to use it would be accessing the wrapped map directly (an obvious transgression) and doing any kind of iteration on it without synchronization (a pitfall shared with `Hashtable`). This is why I think `Hashtable` doesn't have much to offer in comparison. – Marko Topolnik Jan 24 '14 at 21:24

1 Answers1

4

ConcurrentHashMap will do just fine. It has internal synchronization to prevent these sorts of problems. It also has other methods that you may find helpful, such as putIfAbsent.

Its main disadvantage relative to Collections.synchronizedMap is a larger memory footprint.

yshavit
  • 42,327
  • 7
  • 87
  • 124