HashTable and ConCurrentHashMap Overview

HashTable

  • + Linked list to achieve the underlying array, whether key or value can not be null, thread-safe, thread-safe way to achieve lock the entire HashTable when data is modified, low efficiency, ConcurrentHashMap do the relevant optimization
  • The initial size of 11, expansion: newsize = olesize * 2 + 1
  • The method of calculating the index: index = (hash & 0x7FFFFFFF)% tab.length

ConcurrentHashMap

  • Using bottom segment array list + achieve thread-safe
  • Through the whole Map is divided into N Segment, we can provide the same thread-safe, but to enhance the efficiency of N times, 16 times the default upgrade. (Read operation does not lock because HashEntry the value of the variable is volatile, but also to ensure to read the latest value.
  • Hashtable is synchronized for the entire Hash table, i.e., each exclusive thread to lock an entire table, allowing multiple modifications of ConcurrentHashMap concurrently, the key is the use of separation techniques Lock
  • Some methods require 跨段, such as size () and containsValue (), they may need 锁定整个表而而不仅仅是某个段, which requires the order锁定所有段,操作完毕后,又按顺序释放所有段的锁 ( 有面试题问ConcurrentHashMap的size()如何操作?)
  • Expansion: the expansion segment (the segment element segment corresponds to more than 75% of the length of the array Entry trigger expansion, the expansion will not be the entire the Map), prior to insertion detecting or need expansion, expansion effectively prevent invalid

In the memory structure than HashMap ConcurrentHashMap more of a class Segment , the Segment is a reentrant lock.

ConcurrentHashMap segmentation technique is to use a lock to ensure thread-safe.

Lock segmentation technique: first data segments by storing, for each piece of data and with a lock, when a thread holding the lock access data wherein a time segment, the other segment of data can be accessible to other threads.

ConcurrentHashMap provides the Hashtable and SynchronizedMap different lock mechanisms. Locking mechanism employed is a Hashtable lock the entire hash table, which at the same time can only be operated by one thread; and it is time to lock in ConcurrentHashMap a barrel.

ConcurrentHashMap by default hash table is divided into 16 buckets, such as get, put, remove other common operations only need to use the lock barrel currently. In this way, the original can only enter a thread, now able to write while 16 threads of execution, improve concurrency is obvious.

  • 通过锁分段技术保证并发环境下的写操作

  • 通过 HashEntry的不变性、Volatile变量的内存可见性和加锁重读机制保证高效、安全的读操作

  • 通过不加锁和加锁两种方案控制跨段操作的的安全性

HashEntry used to package a particular key-value pair is a typical quad. Entry to the HashMap 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 an important reason . next domain is declared it means that we can not add itself as the final from the middle or tail hash chains or delete nodes, because it needs to be modified next reference value, so modify all nodes can only start from the head. For the put operation, you can always add to the head Hash chain. But for the remove operation, you may need to remove a node from the middle, which need to be deleted to copy the entire front of all the nodes of the (re new) again, the last point you want to delete a node node to the next node (which comes ConcurrentHashMap It will be detailed when the delete operation). In particular, due to 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.

HashMap and HashTable difference

Different default capacities, different expansion

Thread safety: HashTable Security

Different efficiency: HashTable to be slow, because the lock

CocurrentHashMap can be used instead of Hashtable do?

We know that Hashtable is synchronized , but better ConcurrentHashMap synchronization performance, because it is only a part of the map to lock in accordance with the synchronization level

ConcurrentHashMap course you can replace HashTable, but HashTable provide stronger security thread

They can be used in a multithreaded environment 但是当 Hashtable 的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间. Since the introduction of the ConcurrentHashMap division (segmentation), no matter how big it gets, just need to lock a part of the Map, other threads do not need to wait until the iteration is complete to access Map.简而言之,在迭代的过程中,ConcurrentHashMap 仅仅锁定 Map 的某个部分,而 Hashtable 则会锁定整个 Map

CocurrentHashMap(JDK 1.7)

CocurrentHashMap by Segment arrays and linked lists and arrays composed HashEntry

Segment based re-entry lock (ReentrantLock): a segment lock contention. Each element of a linked list structure HashEntry, using a Hash algorithm determines the index of the home segment, i.e. when the corresponding changes need to lock on a competitive. ConcurrentHashMap support CurrencyLevel (Segment number of array) of thread concurrency. Whenever a thread holding the lock access to a Segment, will not affect any other Segment

The core data such as value, and the list is volatile modified to ensure the visibility at the time of acquisition

First Segment by targeting key, followed by the specific put in operation following the corresponding Segment:

Segment table in the current target HashEntry through the hashcode key.

Traverses the HashEntry, if not empty it is determined that the incoming key and the current traversal key for equality, equal to the old value is overwritten

It is not empty and you need to create a HashEntry added to the Segment while will first determine whether the capacity is needed

Finally, we will lift the current lock Segment acquired in 1

Although HashEntry in the volatile keyword value is modified, but does not guarantee atomicity concurrent, so still need to put the lock processing operations

The first step when attempts to get a lock, there is certainly competition if there is a failure to obtain other threads, then use scanAndLockForPut () acquire spin lock

Try to get the spin lock

If the number of retries reached MAX_SCAN_RETRIES blocking locks will be changed to get, guarantee for success. Finally, the lifting of the current lock Segment

CocurrentHashMap(JDK 1.8)

CocurrentHashMap abandoned the original Segment segment lock, using CAS + synchronized to ensure the safety of concurrency. Which we have used volatile val next modification to ensure visibility.

The most important feature is the introduction of CAS

Native code is implemented by means of Unsafe. CAS has three operands, memory value V, the expected value of the old A, to be modified a new value B. If and only if the expected value of the A and V are the same memory value, the memory value V revised to B, or do nothing. Unsafe be implemented by CPU instructions cmpxchg.

CAS Example

SizeCtl control is achieved with CAS:

-1 for initializing table

N -N-1 expressed threads expansion operation in progress

If the table is not initialized, you need to initialize table showing the size of

If the table initialization is complete, the capacity of the table indicates, the default is 0.75 times the size of the table, calculated by the formula 0.75 (n - (n >>> 2))

CAS problems occur: ABA

Solution: adding a version number of variables, each modification, version number plus 1, when comparing compare the version number.

put process

The key calculated hashcode

Determine the need to initialize

By targeting key out of the Node, if empty indicates the current position data can be written using CAS attempts to write, it fails to ensure the success of spin

If the current position of the hashcode == MOVED == -1, it is required for expansion

If not satisfied, the lock synchronized write data using

If the number is greater than TREEIFY_THRESHOLD will have to be converted to red-black tree

get process

The calculated hashcode addressing, if the return value to less directly on the tub

If it is a red-black tree to get the value in the manner of the tree

It does not meet traverse the list to get the value in accordance with the way

Guess you like

Origin blog.csdn.net/qunqunstyle99/article/details/94591627