Java synchronized block vs concurrentHashMap vs Co

2020-08-23 00:58发布

问题:

Say If have a synchronized method and within that method, I update a hashmap like this:

public synchronized void method1()
{
    myHashMap.clear();
    //populate the hashmap, takes about 5 seconds.
}

now while the method1 is running and the hashmap is being re-populated, if there are other threads tring to get the value of the hashmap, I assume they will get blocked?

Now instead of using sync method, if I change hashmap to ConcurrentHashMap like below, what's the behaviour?

public void method1()
{
     myConcurrentHashMap.clear();
    //populate the hashmap, takes about 5 seconds.
}

what if i use Collections.synchronizedMap ? is it the same?

回答1:

If you want to have all read and write actions to your HashMap synchronized, you need to put the synchronize on all methods accessing the HashMap; it is not enough to block just one method.

ConcurrentHashMap allows thread-safe access to your data without locking. That means you can add/remove values in one thread and at the same time get values out in another thread without running into an exception. See also the documentation of ConcurrentHashMap



回答2:

CHM(ConcurrentHashMap), instead of synchronizing every method on a common lock, restricting access to a single thread at a time, it uses a finer-grained locking mechanism called lock striping to allow a greater degree of shared access. Arbitrarily many reading threads can access the map concurrently, readers can access the map concurrently with writers, and a limited number of writers can modify the map concurrently. The result is far higher throughput under concurrent access, with little performance penalty for single-threaded access. ConcurrentHashMap, along with the other concurrent collections, further improve on the synchronized collection classes by providing iterators that do not throw ConcurrentModificationException, thus eliminating the need to lock the collection during iteration.

As with all improvements, there are still a few tradeoffs. The semantics of methods that operate on the entire Map, such as size and isEmpty, have been slightly weakened to reflect the concurrent nature of the collection. Since the result of size could be out of date by the time it is computed, it is really only an estimate, so size is allowed to return an approximation instead of an exact count. While at first this may seem disturbing, in reality methods like size and isEmpty are far less useful in concurrent environments because these quantities are moving targets.



Secondly, Collections.synchronizedMap

It's just simple HashMap with synchronized methods - I'd call it deprecated dute to CHM



回答3:

you could probably do

volatile private HashMap map = newMap();

private HashMap newMap() {
    HashMap map = new HashMap();
    //populate the hashmap, takes about 5 seconds
    return map;
}

public void updateMap() {
    map = newMap();
}

A reader sees a constant map, so reads don't require synchronization, and are not blocked.