Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a ConcurrentHashMap need to be wrapped in a synchronized block?

Do all non-retreival operations on a ConcurrentHashMap (put(), remove() etc.) need to be wrapped in a synchronized(this) block? I understand that all of these operations are thread-safe, so is there any real benefit/need in doing so? The only operations used are put() and remove().

protected final Map<String, String> mapDataStore = new ConcurrentHashMap<String, String>();  public void updateDataStore(final String key, final String value) {     ...     synchronized (this) {         mapDataStore.put(key, value);     }     ... } 
like image 228
MeanwhileInHell Avatar asked Sep 23 '14 15:09

MeanwhileInHell


People also ask

Does ConcurrentHashMap need to be synchronized?

ConcurrentHashMap is thread-safe therefore multiple threads can operate on a single object without any problem. In ConcurrentHashMap, the Object is divided into a number of segments according to the concurrency level. By default, it allows 16 thread to read and write from the Map without any synchronization.

Do you need to lock ConcurrentHashMap?

In ConcurrentHashMap, at a time any number of threads can perform retrieval operation but for updated in the object, the thread must lock the particular segment in which the thread wants to operate.

What is the best benefit of using a ConcurrentHashMap instead of a HashMap?

Advantages of ConcurrentHashMap over HashMap The advantages of using ConcurrentHashMap are as follows: It provides very high concurrency in a multi-threaded environment. The read operation can be very fast when the write operation is done with a lock. It provides No object-level Locking.

Is ConcurrentHashMap blocked?

The simple answer is no. Unless there is something else you are not telling us, the get call won't block for longer than a microsecond or so. The source code for the get method and its helper method are below. As you can see, most of the work is done without any locks whatsoever.


1 Answers

No, you are losing the benefits of ConcurrentHashMap by doing that. You may as well be using a HashMap with synchronized or synchronizedMap() to lock the whole table (which is what you do when wrapping operations in synchronized, since the monitor implied is the entire object instance.)

The purpose of ConcurrentHashMap is to increase the throughput of your concurrent code by allowing concurrent read/writes on the table without locking the entire table. The table supports this internally by using lock striping (multiple locks instead of one, with each lock assigned to a set of hash buckets - see Java Concurrency in Practice by Goetz et al).

Once you are using ConcurrentHashMap, all standard map methods (put(), remove(), etc.) become atomic by virtue of the lock striping etc. in the implementation. The only tradeoffs are that methods like size() and isEmpty() may not necessarily return accurate results, since the only way they could would be for all operations to lock the whole table.

The ConcurrentMap interface interface also adds new atomic compound operations like putIfAbsent() (put something only if it the key is not already in the map), remove() accepting both key and value (remove an entry only if its value equals a parameter you pass), etc. These operations used to require locking the whole table because they needed two method calls to accomplish (e.g. putIfAbsent() would need calls to both containsKey() and put(), wrapped inside one synchronized block, if you were using a standard Map implementation.) Once again, you gain greater throughput using these methods, by avoiding locking the entire table.

like image 146
sparc_spread Avatar answered Oct 20 '22 00:10

sparc_spread