Java. util. Concurrent. concurrenthashmap

Source: Internet
Author: User

 

I. Introduction

Concurrenthashmap is a concurrency Implementation of map. The read operations of elements in this class are unlocked, and the write operations need to be synchronized. This is very suitable for read operations far greater than write operations. In the implementation process, concurrenthashmap divides all elements into several segments, each of which is independent. Locking on a segment does not affect other segment operations. The segment itself is a hashtable. For a <key, value> pair that joins concurrenthashmap, the high hash value of the key is used to index the segment, while the low value is used to index the segment.

Ii. segment implementation

Segment is the basic segment of the concurrenthashmap storage element. It is a hashtable implementation, and there is no lock during read operations. Write needs to be synchronized and is defined as follows:

Public class concurrenthashmap <K, V> extends abstractmap <K, V> implements concurrentmap <K, V>, serializable {/*** key, hash, * value can be overwritten */static final class hashentry <K, V> {final K key; Final int hash; volatile V value; Final hashentry <K, v> next ;...} static final class segment <K, V> extends reentrantlock implements serializable {transient volatile int count; transient volatile hashentry [] Table; // when the number of elements in the segment reaches threshold, need rehash transient int threshold ;}...}

Read operation of segment:

Static final class segment <K, V> extends reentrantlock implements serializable {hashentry <K, V> getfirst (INT hash) {hashentry [] tab = table; Return (hashentry <K, v>) tab [hash & (tab. length-1)];} V get (Object key, int hash) {// The operation is unlocked if (count! = 0) {// read-volatile hashentry <K, V> E = getfirst (hash); While (E! = NULL) {If (E. Hash = hash & Key. Equals (E. Key) {v = E. value; If (V! = NULL) return V; return readvalueunderlock (E); // recheck} e = E. Next;} return NULL ;}...

Because the key and next in the hashentry are both final, the operation on the segment cannot affect the relative sequence between the hashentry list, and the value is variable. When the first read value fails, try to lock the read.

The replace operation of segment:

Static final class segment <K, V> extends reentrantlock implements serializable {/*** replace operation is local replacement, hashentry value is not final */Boolean Replace (K key, int hash, V oldvalue, V newvalue) {lock (); // The replace operation is a synchronized try {// obtain the hashentry list corresponding to this hash value hashentry <K, v> E = getfirst (hash); While (E! = NULL & (E. Hash! = Hash |! Key. Equals (E. Key) E = E. Next; Boolean replaced = false; If (E! = NULL & oldvalue. equals (E. value) {// replace replaced = true; E. value = newvalue;} return replaced;} finally {unlock ();}}...}

Put operation of segmet:

Static final class segment <K, V> extends reentrantlock implements serializable {v put (K key, int hash, V value, Boolean onlyifabsent) {lock (); // put is the synchronized try {int c = count; If (C ++> threshold) // ensure capacity rehash (); hashentry [] tab = table; int Index = hash & (tab. length-1); hashentry <K, V> first = (hashentry <K, V>) tab [Index]; hashentry <K, V> E = first; while (E! = NULL & (E. Hash! = Hash |! Key. Equals (E. Key) E = E. Next; V oldvalue; If (E! = NULL) {// if it already exists, update oldvalue = E. value; If (! Onlyifabsent) E. value = value;} else {// Add to the list header oldvalue = NULL; ++ modcount; // The next of hashentry is read-only, the newly added entry can only be placed on the tab [Index] = new hashentry <K, V> (Key, hash, first, value); Count = C; // write-volatile} return oldvalue;} finally {unlock ();}}...}

The remove operation of segment is a copy on write method, which retains the list of deleted elements, and the hashentry before the copy element is deleted:

Static final class segment <K, V> extends reentrantlock implements serializable {v remove (Object key, int hash, object Value) {lock (); try {int c = count-1; hashentry [] tab = table; int Index = hash & (tab. length-1); hashentry <K, V> first = (hashentry <K, V>) tab [Index]; hashentry <K, V> E = first; while (E! = NULL & (E. Hash! = Hash |! Key. Equals (E. Key) E = E. Next; V oldvalue = NULL; If (E! = NULL) {v = E. value; If (value = NULL | value. equals (V) {// copy on write oldvalue = V; ++ modcount; // The list after e can be retained, you only need to re-create the hashentry before e to obtain the hashentry <K, V> newfirst = E. next; // copy hashentry for (hashentry <K, V> P = first; P! = E; P = P. next) newfirst = new hashentry <K, V> (P. key, P. hash, newfirst, P. value); tab [Index] = newfirst; Count = C; // write-volatile} return oldvalue;} finally {unlock ();}}...}

The rehash operation of segment is particularly implemented. To ensure that there are as few copy elements as possible during the rehash process, the number of entry entries of segment increases by a factor of 2 in rehash, this ensures that an entry is either in the original list or in the next list after rehash:

Static final class segment <K, V> extends reentrantlock implements serializable {void rehash () {// reference table hashentry [] oldtable = table; int oldcapacity = oldtable. length; If (oldcapacity> = maximum_capacity) return; // shift one to the right by multiplying 2 hashentry [] newtable = new hashentry [oldcapacity <1]; Threshold = (INT) (newtable. length * loadfactor); int sizemask = newtable. length-1; for (INT I = 0; I <oldca Pacity; I ++) {// list of entry I hashentry <K, V> E = (hashentry <K, V>) oldtable [I]; If (E! = NULL) {hashentry <K, V> next = E. next; // index int idx = E on the new table. hash & sizemask; If (next = NULL) newtable [idx] = E; else {// find the end of the entry list, the same idx elements after rehash // these elements do not need to be copied hashentry <K, V> lastrun = E; int lastidx = idx; For (hashentry <K, v> last = next; last! = NULL; last = last. Next) {int K = last. Hash & sizemask; If (K! = Lastidx) {lastidx = K; lastrun = last ;}}// mount the entire list after lastrun to the new location. newtable [lastidx] = lastrun; // clone all remaining nodes for (hashentry <K, V> P = E; P! = Lastrun; P = P. next) {int K = P. hash & sizemask; hashentry <K, V> N = (hashentry <K, V>) newtable [k]; newtable [k] = new hashentry <K, V> (P. key, P. hash, N, P. value) ;}}} table = newtable ;}...}

 

Iii. concurrenthashmap implementation

Based on the segment, concurrenthashmap first hashes the <key, value> pair to a segment, and then manages the entry by segment.

Get Implementation of concurrenthashmap:

public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>           implements ConcurrentMap<K, V>, Serializable {         final Segment<K,V> segmentFor(int hash) {           return (Segment<K,V>) segments[(hash >>> segmentShift) & segmentMask];       }         public V get(Object key) {           int hash = hash(key); // throws NullPointerException if key null           return segmentFor(hash).get(key, hash);       }       ...   }  

Put and get methods of concurrenthashmap:

public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>           implements ConcurrentMap<K, V>, Serializable {         public V put(K key, V value) {           if (value == null)               throw new NullPointerException();           int hash = hash(key);           return segmentFor(hash).put(key, hash, value, false);       }         public V remove(Object key) {           int hash = hash(key);           return segmentFor(hash).remove(key, hash, null);       }       ...   }  

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.