views:

105

answers:

3

I need a HashMap that is accessible from multiple threads.

There are two simple options, using a normal HashMap and synchronizing on it or using a ConcurrentHashMap.

Since ConcurrentHashMap does not block on read operations it seems much better suited for my needs (almost exclusively reads, almost never updates). On the other hand, I expect very low concurrency anyway, so there should be no blocking (just the cost of managing the lock).

The Map will also be very small (under ten entries), if that makes a difference.

Compared to a regular HashMap, how much more costly are the read and write operations (I am assuming that they are)? Or is ConcurrentHashMap just always better when there might be even a moderate level of concurrent access, regardless of read/update ratio and size?

+1  A: 

CHM pays some penalty for the use of Atomic* operations under the covers, when compared to HashMap. How much? Guess what... measure it in your app... ;-)

If you find that you actually have a performance problem, there's probably a very specialized solution for <10 entries that would be cheaper than any solution assembled out of java.util land, but I'd not jump to that until you know you have a performance issue.

andersoj
The question I have is if I should jump to using ConcurrentHashMap before I know that I have a performance issue. I would not want to do that if CHM was actually slower than HashMap in the case of no concurrency.
Thilo
I guess I'd use `CHM` if it's immediately apparent that you can get the concurrency control you want w/ `putIfAbsent()` and the like; I'd use `synchronized(normalHashMap)` if you know in advance that the `put()` operation is going to be complex. (Optimizing either one later if it's an issue...)
andersoj
+2  A: 

On the other hand, I expect very low concurrency anyway, so there should be no blocking (just the cost of managing the lock).

The cost of acquiring and releasing an uncontend Java mutex (primitive lock) is miniscule. So if you believe that the probability of contention is very low then a simple HashMap is probably your best bet.

But this is all conjecture. Unless and until you have actually profiled your application, all time spent on speculative optimization is most likely (*) time wasted.

* ... unless you have a really good intuition.

Stephen C
Stephen C is right (his rep suggests this is a habit). Uncontended locks are speedy in the general case... I end up reaching for CHM too quickly, perhaps.
andersoj
What about scaling though? Whats expected and what might happen are completely different. If locking/unlocking is so small, just use `ConcurrentHashMap` and move on
TheLQ
@TheLQ - it is the the other overheads (apart from locking) of using ConcurrentHashMap that are the concern. You don't just throw CCM at a problem on the assumption that scalability *will* be an issue. You measure first!
Stephen C
"You don't just throw CCM at a problem on the assumption that scalability will be an issue." That is exactly the reply I was fishing for. Now all I need are some guidelines on when CHM will be justified (because not everyone can be expected to profile their app every time).
Thilo
@Stephen Unless your managing thousands of ComcurrentHashMaps, the overhead is so small that you would never notice it. I go by this principle: If it will be accessed and changed by multiple threads, use a ConcurrentHashMap. This stops me from wasting hours on threading issues that only appear sometimes under certain small conditions, stuff that doesn't always show up in your profile. @Thilo, that principle would work
TheLQ
+1  A: 

In terms of throughput and performance, the overhead is usually negligible.

On a different note, the memory footprint of a ConcurrentHashMap (at the instance level) is somewhat larger than a HashMap. If you have a large number of small-sized CHMs, this overhead might add up.

sjlee