Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConcurrentHashMap read and write locks

I am trying to find answer to these, but not able to find it on Google or in Java docs.

Case 1: in ConcurrentHashMap, suppose a thread t1 is reading from segment n, and at same another thread t2 want to write on the same segment n:

Question 1: will these two operations will be one after another, or they will execute simultaneously?


Case 2: in ConcurrentHashMap, suppose a thread t1 is writing on segment n, and at same another thread t2 want to read from the same segment n,

Question 2: will these two operations will be one after another, or they will execute simultaneously?

like image 965
lowLatency Avatar asked Apr 19 '13 13:04

lowLatency


People also ask

Does ConcurrentHashMap use read Write lock?

So unlike hashtable, we perform any sort of operation ( update ,delete ,read ,create) without locking on entire map in ConcurrentHashMap. Retrieval operations (including get) generally do not block. It uses the concept of volatile in this case., so may overlap with update operations (including put and remove).

What happen if two threads are reading and writing simultaneously in a HashMap?

There can't be two threads changing things at the same time. The whole point of using such data structures is that they prevent more than one thread updating that "core internal data" at the same time. Having two threads that change the map at the very same point time is not possible.

Can multiple threads read ConcurrentHashMap at the same time?

Size of Segments and concurrency level of ConcurrentHashMap By default ConcurrentHashMap has segment array size as 16 so simultaneously 16 Threads can put data in map considering each thread is working on separate Segment array index.

Is ConcurrentHashMap thread safe?

ConcurrentHashMap class achieves thread-safety by dividing the map into segments, the lock is required not for the entire object but for one segment, i.e one thread requires a lock of one segment. In ConcurrentHashap the read operation doesn't require any lock.


2 Answers

I think javadoc answers both your questions:

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset. For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries.

Segments are for update operations:

The allowed concurrency among update operations is guided by the optional concurrencyLevel constructor argument (default 16), which is used as a hint for internal sizing.

So, in short, reads are not blocked (it is implemented as reading volatile variables). Writes could block each other if they write in the same segment.

like image 57
kan Avatar answered Oct 16 '22 21:10

kan


According to ConcurrentHashMap Oracle docs,

The constructor of ConcurrentHashMap looks like this :

public ConcurrentHashMap (int initialCapacity, float loadFactor, int concurrencyLevel)

So the above line creates a new, empty map with the specified initial capacity, load factor and concurrency level. where, Important Parameters to consider from ConcurrentHashMap Constructor:

  • initialCapacity - the initial capacity. The implementation performs internal sizing to accommodate this many elements.
  • concurrencyLevel - the estimated number of concurrently updating threads. The implementation performs internal sizing to try to accommodate this many threads.

In the ConcurrentHashMap Api , you will find the following constants.

  • static final int DEFAULT_INITIAL_CAPACITY = 16;
  • static final int DEFAULT_CONCURRENCY_LEVEL = 16;

initial capacity parameter and concurrency level parameters of ConcurrentHashMap constructor (or Object) are set to 16 by default.

Thus, instead of a map wide lock, ConcurrentHashMap maintains a list of 16 locks by default ( number of locks equal to the initial capacity , which is by default 16) each of which is used to lock on a single bucket of the Map.This indicates that 16 threads (number of threads equal to the concurrency level , which is by default 16) can modify the collection at the same time , given ,each thread works on different bucket. So unlike hashtable, we perform any sort of operation ( update ,delete ,read ,create) without locking on entire map in ConcurrentHashMap.

Retrieval operations (including get) generally do not block. It uses the concept of volatile in this case., so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset.

The allowed concurrency among update operations is guided by the optional concurrencyLevel constructor argument (default 16), which is used as a hint for internal sizing. The table is internally partitioned to try to permit the indicated number of concurrent updates without contention. Because placement in hash tables is essentially random, the actual concurrency will vary. Ideally, you should choose a value to accommodate as many threads as will ever concurrently modify the table. Using a significantly higher value than you need can waste space and time, and a significantly lower value can lead to thread contention.

I hope it helps!

like image 34
Aman Goel Avatar answered Oct 16 '22 23:10

Aman Goel