22

I am working with around 1000 elements in concurrenthashmap . Default concurrency level is 16 . can anyone help me with some algorithm or factors from which i can identify the concurrency level suitable for my scenario or in what way a concurrency level affects the processing of multiple threads .

   ConcurrentHashMap<String, String> map=new ConcurrentHashMap<String, String>(500,1,20);             

20 is my concurrency level (dummy value) .Need to set this efficiently

csk
  • 566
  • 1
  • 5
  • 15

5 Answers5

23

According to docs:

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.

So you need to answer 1 question:

What is the number of threads that will ever concurrently modify the table?

Tala
  • 8,888
  • 5
  • 34
  • 38
  • 1
    If the answer is 100 then you can set Concurrency level to 100. – Tala Aug 28 '13 at 12:55
  • @Tala Assume that if my system has 100 threads. And 90 threads will be traversing this map and at max 10 threads will try modifying (put/remove) this map at a time, then what is Concurrency level? Please respond. – Kanagavelu Sugumar Jun 26 '14 at 09:08
  • I would set it to ten, if in your case it is really critical that no thread is waiting, you can set to 16 for example. – Tala Jun 27 '14 at 09:42
13

Java 8:

Now the ConcurrentHashMap does not use a fixed lock striping scheme at all, instead each bucket serves as a “stripe” using intrinsic synchronization.

Code from source:

/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
    ...
    Node<K,V> f; int n, i, fh;
    ...
    else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
    ...
       synchronized (f) {
           ...
       }
}

And the constructor has the parameter just use it as a size hint as docs say.

concurrencyLevel - the estimated number of concurrently updating threads. The implementation may use this value as a sizing hint.

And the source:

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel) {
    if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
        throw new IllegalArgumentException();
    if (initialCapacity < concurrencyLevel)   // Use at least as many bins
        initialCapacity = concurrencyLevel;   // as estimated threads
    long size = (long)(1.0 + (long)initialCapacity / loadFactor);
    int cap = (size >= (long)MAXIMUM_CAPACITY) ?
        MAXIMUM_CAPACITY : tableSizeFor((int)size);
    this.sizeCtl = cap;
}

So you don't need to consider it by yourself, ConcurrentHashMap will handle it for you.

Tony
  • 5,972
  • 2
  • 39
  • 58
  • from comments to java 8 ConcurrentHashMap implementation: – qwazer Aug 26 '16 at 06:47
  • We do not want to waste the space required to associate a distinct lock object with each bin, so instead use the first node of a bin list itself as a lock. Locking support for these locks relies on builtin "synchronized" monitors. – qwazer Aug 26 '16 at 06:48
2

ConcurrentHashMap allows multiple readers to read concurrently without any blocking. This is achieved by partitioning Map into different parts based on concurrency level and locking only a portion of Map during updates. Default concurrency level is 16, and accordingly Map is divided into 16 part and each part is governed with different lock. This means, 16 thread can operate on Map simultaneously, until they are operating on different part of Map. This makes ConcurrentHashMap high performance despite keeping thread-safety intact.

1

16 is the default number of regions that your map will be split into. ConcurrentHashMap, in case of reader threads, is done (in almost all cases) without locking at all. The number of writer threads is the thing you need to worry. And this number should be equal to the number of regions you have.

Eugene
  • 117,005
  • 15
  • 201
  • 306
0

So,concurrency level is the equal to to the writer threads.And map will also segmented equals to the value of concurrency level.

harit
  • 33
  • 6
  • For JDK8+, Segment is now there just for backward compatibility. Now synchronization is at bucket level and value object itself is used as lock. – Mandroid Jan 02 '22 at 10:47