Java Reference
In-Depth Information
11.5. Example: Comparing Map Performance
The single-threaded performance of
ConcurrentHashMap
is slightly better than that of a
synchronized
HashMap
, but it is in concurrent use that it really shines. The implementation
of
ConcurrentHashMap
assumes the most common operation is retrieving a value that
already exists, and is therefore optimized to provide highest performance and concurrency
for successful
get
operations.
The major scalability impediment for the synchronized
Map
implementations is that there is
a single lock for the entire map, so only one thread can access the map at a time. On the oth-
er hand,
ConcurrentHashMap
does no locking for most successful read operations, and
uses lock striping for write operations and those few read operations that do require locking.
As a result, multiple threads can access the
Map
concurrently without blocking.
ConcurrentHashMap
,
ConcurrentSkipListMap
, and
HashMap
and
TreeMap
wrapped with
synchronizedMap
. The first two are thread-safe by design; the latter two
are made thread-safe by the synchronized wrapper. In each run,
N
threads concurrently ex-
ecute a tight loop that selects a random key and attempts to retrieve the value corresponding
to that key. If the value is not present, it is added to the
Map
with probability
p
= .6, and
if it is present, is removed with probability
p
= .02. The tests were run under a pre-release
build of Java 6 on an 8-way Sparc V880, and the graph displays throughput normalized to
the onethread case for
ConcurrentHashMap
. (The scalability gap between the concurrent
and synchronized collections is even larger on Java 5.0.)
The data for
ConcurrentHashMap
and
ConcurrentSkipListMap
shows that they
scale well to large numbers of threads; throughput continues to improve as threads are added.
While the numbers of threads in
Figure 11.3
may not seem large, this test program generates
more contention per thread than a typical application because it does little other than pound
on the
Map
; a real program would do additional thread-local work in each iteration.