java8 ConcurrentHashMap

原创 2016年05月31日 19:12:24

node结构

 static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;

        Node(int hash, K key, V val, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.val = val;
            this.next = next;
        }

        public final K getKey()       { return key; }
        public final V getValue()     { return val; }
        public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }
        public final String toString(){ return key + "=" + val; }
        public final V setValue(V value) {
            throw new UnsupportedOperationException();
        }

        public final boolean equals(Object o) {
            Object k, v, u; Map.Entry<?,?> e;
            return ((o instanceof Map.Entry) &&
                    (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
                    (v = e.getValue()) != null &&
                    (k == key || k.equals(key)) &&
                    (v == (u = val) || v.equals(u)));
        }

        /**
         * Virtualized support for map.get(); overridden in subclasses.
         */
        Node<K,V> find(int h, Object k) {
            Node<K,V> e = this;
            if (k != null) {
                do {
                    K ek;
                    if (e.hash == h &&
                        ((ek = e.key) == k || (ek != null && k.equals(ek))))
                        return e;
                } while ((e = e.next) != null);
            }
            return null;
        }
    }

  static final int MOVED     = -1; // hash for forwarding nodes   forwardNode类型节点的hash
  static final int TREEBIN   = -2; // hash for roots of trees     树形节点hash


/**
     * Table initialization and resizing control.  When negative, the 负数时候是在初始化或者重建
     * table is being initialized or resized: -1 for initialization,
     * else -(1 + the number of active resizing threads).  Otherwise,
     * when table is null, holds the initial table size to use upon
     * creation, or 0 for default. After initialization, holds the
     * next element count value upon which to resize the table.
     */
    private transient volatile int sizeCtl;

put以及transfer过程:

1、不允许Null的key或者value

2、一个死循环用来put,何时put成功何时跳出,第一次put初始化table

3、tabAt(tab, i = (n - 1) & hash)找到当前node应该在table位置处的node,若是为null,不加锁利用casTabAt()方法放进去,break

4、如果这个node不是null,而是forwardNode类型,说明这个节点以及被transfer了,这使用helpTransfer(tab, f);帮助transfer,得到新的table,进行下一次循环put

5、如果找到的node不是null,也不是forwardNode类型,即找到了链表或者tree的头结点,对这个头结点加锁

遍历链表或者tree,比较key和hash,找到则替换value,到尾节点则新加一个节点


6、transfer扩容方法,允许多个线程扩容,利用了private transient volatile Node<K,V>[] nextTable;以及forwardNode

    一个线程扩容时候会把nextTable指向当前操作nextTab,另一个线程在put时候遇到forwardNode节点时候,使用helpTransfer,会先拿到nextTable,然后进入扩容方法,多个线程扩容操作的nextTable会是一个。

   每次处理完table中i出节点,就会把这处的节点置为forwardNode节点类型

  遍历到空节点,也置为forwardNode节点类型

  如果遍历到forwardNode类型,则跳过不处理

   拷贝节点以及list就跟hashmap类似,不过这个过程对头结点做了加锁

 


   //原子操作 
   //可以理解为得到tab的i处节点
    static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
        return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
    }
   //如果tab的i处节点为c,则更新为v
    static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                        Node<K,V> c, Node<K,V> v) {
        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
    }
   //<span><span class="comment">设置节点位置的值</span><span>  </span></span>
    static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
    }


版权声明:本文为博主原创文章,未经博主允许不得转载。

【Java8源码分析】并发包-ConcurrentHashMap(一)

一、CAS原理简介 Java8中,ConcurrentHashMap摒弃了Segment的概念,而是启用了一种全新的方式实现:利用CAS算法。它沿用了HashMap的思想,底层依然由“数组”+链表+...
  • linxdcn
  • linxdcn
  • 2017年05月26日 21:09
  • 304

JDK源码学习(8)-java.util.concurrent.ConcurrentHashMap

主要是jdk8的线程安全hashMap的源码分析

ConcurrentHashMap源码分析--Java8

如果还停留在锁分离、Segment,那已经out了。 Segment虽保留,但已经简化属性,仅仅是为了兼容旧版本。 CAS算法;unsafe.compareAndSwapInt(this, valu...

为并发而生的 ConcurrentHashMap(Java 8)

HashMap 是我们日常最常见的一种容器,它以键值对的形式完成对数据的存储,但众所周知,它在高并发的情境下是不安全的。尤其是在 jdk 1.8 之前,rehash 的过程中采用头插法转移结点,高并发...

【Java8源码分析】并发包-ConcurrentHashMap(二)

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72871732 上一篇并发包-ConcurrentHashMap(一)主要介绍了Con...
  • linxdcn
  • linxdcn
  • 2017年06月05日 23:26
  • 606

Java8---4.对HashMap和ConcurrentHashMap的改进

Java8为何比Java7速度更快,从底层数据结构开始说起 1.HashMap 在Java7中,HashMap采用的是数组+链表的形式存储的,(默认bucket数目16,负载因子0.75) 具体见 H...

java8中对ConcurrentHashMap的改进

一、简单回顾ConcurrentHashMap在jdk1.7中的设计     先简单看下ConcurrentHashMap类在jdk1.7中的设计,其基本结构如图所示: 每一个segment都...

JDK源码-java8-ConcurrentHashMap的实现原理与应用

本文目录 本文目录 开篇明志 什么是ConcurrentHashMap 为什么要使用ConcurrentHashMap 四成员常量和变量 内部类 Node TreeNode TreeBin Forwa...

ConcurrentHashMap与红黑树实现分析Java8

本文学习知识点 1、二叉查找树,以及二叉树查找带来的问题。 2、平衡二叉树及好处。 3、红黑树的定义及构造。 4、ConcurrentHashMap中红黑树的构造。 在正式分析红黑树之前,有...

Java 8 中的ConcurrentHashMap源码分析

在HashMap的分析中,介绍了hashmap不是线程安全的,其在并发环境使用fail-fast策略来抛出由并发错误导致的异常。 先来看下Hashtable这个线程安全的容器,其虽然是线程安全的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java8 ConcurrentHashMap
举报原因:
原因补充:

(最多只允许输入30个字)