Overview Map - thoroughly understand ConcurrentHashMap

EDITORIAL

This article about all the source code ConcurrentHashMap are based on JDK 1.6 , there was a little difference between the different versions of the JDK, but does not affect our ConcurrentHashMap data structure, principle and so the overall grasp and understand

ConcurrentHashMap is an important member of the JUC (java.util.concurrent package), which is a thread-safe HashMap is to support efficient concurrent version

ConcurrentHashMap Overview

HashMap is an important member of the Java Collection Framework, the most commonly used is the Map family (shown below) in us a. But unfortunately, HashMap is not thread safe

This drawback HashMap usually cause inconvenience, although HashTable wrapper and packaging by the synchronization in concurrent scenario HashMap (Collections.synchronizedMap (Map <K, V> m)) can replace HashMap, but they are by the use of a global lock to synchronize concurrent access among different threads, and therefore will bring performance issues can not be ignored. Fortunately, JDK for us to solve this problem, it provides an efficient thread-safe version of HashMap - ConcurrentHashMap

In ConcurrentHashMap, whether it is a read or write operation can guarantee high performance: When a read operation is performed (almost) need not locked, and when the write operation through the lock segment technique only operated lock segment without affecting the client access to other segments. In particular, under ideal conditions, ConcurrentHashMap can support 16 concurrent threads of execution write operation (if the concurrency level set to 16), and read any number of threads

Overview Map - thoroughly understand ConcurrentHashMap

ConcurrentHashMap efficient concurrency is through the following three areas to ensure that the

  • By writing in the lock segmentation techniques to ensure concurrent environment
  • By HashEntry invariance, memory, visibility and reread locking mechanism Volatile variables to ensure the efficient and safe operation of reading
  • Span of control operation by not locking and locking two options Security

ConcurrentHashMap defined in the JDK

ConcurrentHashMap class contains two static inner classes

  • HashEntry: used to encapsulate specific K / V Yes, a typical four-tuple
  • Segment: to act as locks, each Segment object guard ConcurrentHashMap whole number of barrels (Segment can be seen as a small hash table), where each barrel is linked by a number of objects up HashEntry list

ConcurrentHashMap creates an array of 16 Segment object in the default concurrency level down, even if the key can hash each Segment guard about 1/16 of the total throughout the hash table bucket.

Class structure definition

ConcurrentHashMap inherited AbstractMap ConcurrentMap interfaces and implements, which is defined in the JDK as follows:

public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
 implements ConcurrentMap<K, V>, Serializable {
 ...
}

Member variable is defined
in comparison with HashMap, ConcurrentHashMap ** adds two attributes for positioning section, and are segmentMask segmentShift. ** In addition, unlike the HashMap it is, of ConcurrentHashMap underlying structure is a Segment array rather than an array Object

final int segmentMask; // 用于定位段,大小等于segments数组的大小减 1,是不可变的

final int segmentShift; // 用于定位段,大小等于32(hash值的位数)减去对segments的大小取以2为底的对数值,是不可变的

final Segment<K,V>[] segments; // ConcurrentHashMap的底层结构是一个Segment数组

Defined segments: Segment
Segment ReentrantLock class inherits from the class, so that the Segment object can act as a lock

Overview Map - thoroughly understand ConcurrentHashMap

In Segment class, count variable is a counter that indicates the number of each array HashEntry object table Segment objects containing management, that is, the total number of HashEntry Segment objects included. Of particular note is that the reason contains a counter in each Segment object, instead of using a global counter ConcurrentHashMap, the consideration of ConcurrentHashMap concurrency: because so when you need to update the counter without locking the entire ConcurrentHashMap

Basic elements: HashEntry
and the HashMap Entry Similarly, HashEntry also includes four similar domains, are key, hash, value and the next. The difference is that, in HashEntry class, key, hash and next fields are declared as final, value field is modified by volatile, and therefore is almost HashEntry objects are immutable, which is ConcurrentHashmap read operation does not require a lock important reason

Since the value field is modified volatile, so it can be read to ensure that the thread read the latest value, which is another important reason ConcurrentHashmap read operation does not require locked.

ConcurrentHashMap constructor

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

This configuration is intended to function configuration having a specified capacity, load factor and the designated number of designated segments / concurrency level (if it is not a power of 2, it is adjusted to a power of 2) empty ConcurrentHashMap

2,ConcurrentHashMap(int initialCapacity, float loadFactor)

This configuration is intended to function configuration having a specified capacity, and a default load factor specified concurrency level (16) empty ConcurrentHashMap

3,ConcurrentHashMap(int initialCapacity)

This configuration is intended to function with a specified capacity configuration, the default load factor (0.75) and the default level of concurrency (16) empty ConcurrentHashMap

4,ConcurrentHashMap()

This configuration is intended to function configuration having a default initial capacity (16), a default load factor (0.75) and the default level of concurrency (16) empty ConcurrentHashMap

5,ConcurrentHashMap(Map<? extends K, ? extends V> m)

This constructor is intended to construct a ConcurrentHashMap the same elements as the specified Map, initial capacity of not less than 16 (particularly depends on the size specified Map), the load factor is 0.75, the concurrency level is 16, a Java Collection Framework specification recommends provided

summary

Here, we mention three very important parameters: the initial capacity , load factor and concurrency level , these three parameters are important parameters that affect the performance of ConcurrentHashMap

ConcurrentHashMap data structure

By using the segment (Segment) The ConcurrentHashMap divided into different parts, ConcurrentHashMap can use different modifications of locks to control different parts of the hash table, thereby allowing multiple modifications performed concurrently, which is locked segmentation techniques ConcurrentHashMap the core substance

ConcurrentHashMap concurrent access

In ConcurrentHashMap, the thread of the mapping table do read operations, generally do not need a lock can be completed, to make structural modifications to the vessel's operation (for example, PUT operation, Remove operation, etc.) need to lock it.

Concurrency among the plurality of segmented locking mechanism with threads write: put (key, vlaue)

In ConcurrentHashMap, the typical structural modification operations, including put, remove and clear, let's first of all to put the operation as an example of the structural modification process do ConcurrentHashMap

public V put(K key, V value) {
 if (value == null)
 throw new NullPointerException();
 int hash = hash(key.hashCode());
 return segmentFor(hash).put(key, hash, value, false);
 }

Unlike ConcurrentHashMap HashMap, both allowed key is null, null values ​​are not allowed value

segmentFor locating segment () method below source

final Segment<K,V> segmentFor(int hash) {
 return segments[(hash >>> segmentShift) & segmentMask];
 }

The high n-bit hash value of the key elements can determine exactly where a Segment of

Code segments put () method is as follows

V put( K key, int hash, V value, boolean onlyIfAbsent )
{
	lock();                                                                                 /* 上锁 */
	try {
		int c = count;
		if ( c++ > threshold )                                                          /* ensure capacity */
			rehash();
		HashEntry<K, V>[] tab = table;                                                  /* table是Volatile的 */
		int		index	= hash & (tab.length - 1);                              /* 定位到段中特定的桶 */
		HashEntry<K, V> first	= tab[index];                                           /* first指向桶中链表的表头 */
		HashEntry<K, V> e	= first;
		/* 检查该桶中是否存在相同key的结点 */
		while ( e != null && (e.hash != hash || !key.equals( e.key ) ) )
			e = e.next;
		V oldValue;
		if ( e != null )                                                                /* 该桶中存在相同key的结点 */
		{
			oldValue = e.value;
			if ( !onlyIfAbsent )
				e.value = value;                                                /* 更新value值 */
		}else {                                                                         /* 该桶中不存在相同key的结点 */
			oldValue = null;
			++modCount;                                                             /* 结构性修改,modCount加1 */
			tab[index]	= new HashEntry<K, V>( key, hash, first, value );       /* 创建HashEntry并将其链到表头 */
			count		= c;                                                    /* write-volatile,count值的更新一定要放在最后一步(volatile变量) */
		}
		return(oldValue);                                                               /* 返回旧值(该桶中不存在相同key的结点,则返回null) */
	} finally {
		unlock();                                                                       /* 在finally子句中解锁 */
	}
}

Compared to HashTable and packaged by the synchronization wrapper HashMap Only one thread read or write operation, ConcurrentHashMap has been a qualitative improvement in the performance of concurrent access. In the ideal situation, ConcurrentHashMap can support 16 concurrent threads of execution write operation (if the concurrency level set to 16), and any number of threads read

This article ends, like a friend little bit of praise and attention, thanks!

Guess you like

Origin blog.csdn.net/qwe123147369/article/details/91559056