1.8ConcurrentHashMap



 

 

使用减小锁粒度的方式实现高并发。实现方式较7及之前有较大的变化,

不在使用segment进行锁分段的技术。

直接使用Node存储值,put操作的时候根据hash到的table的节点进行加锁,

而不是对整个table加锁达到减小锁的粒度实现更高的并发性能。

 

 

 

/**

     * Key-value entry.  This class is never exported out as a

     * user-mutable Map.Entry (i.e., one supporting setValue; see

     * MapEntry below), but can be used for read-only traversals used

     * in bulk tasks.  Subclasses of Node with a negative hash field

     * are special, and contain null keys and values (but are never

     * exported).  Otherwise, keys and vals are never null.

     */

    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;

        }

    }

 

 

一:init初始化,默认的话只是new一个对象返回。知道put的时候再initTable

 

      /**

     * Creates a new, empty map with the default initial table size (16).

     */

    public ConcurrentHashMap() {

    }

 

initTable

  Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];

  table = tab = nt;

 

 

 

 

二:put操作:的时候根据hash到的table的节点进行加锁,而不是对整个table加锁达到减小锁的粒度实现更高的并发性能。

 final V putVal(K key, V value, boolean onlyIfAbsent) {

        if (key == null || value == null) throw new NullPointerException();

        int hash = spread(key.hashCode());

        int binCount = 0;

        for (Node<K,V>[] tab = table;;) {

            Node<K,V> f; int n, i, fh;

            if (tab == null || (n = tab.length) == 0)

                tab = initTable();

            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {

                if (casTabAt(tab, i, null,

                             new Node<K,V>(hash, key, value, null)))

                    break;                   // no lock when adding to empty bin

            }

            else if ((fh = f.hash) == MOVED)

                tab = helpTransfer(tab, f);

            else {

                V oldVal = null;

                synchronized (f) {

                    if (tabAt(tab, i) == f) {

                        if (fh >= 0) {

                            binCount = 1;

                            for (Node<K,V> e = f;; ++binCount) {

                                K ek;

                                if (e.hash == hash &&

                                    ((ek = e.key) == key ||

                                     (ek != null && key.equals(ek)))) {

                                    oldVal = e.val;

                                    if (!onlyIfAbsent)

                                        e.val = value;

                                    break;

                                }

                                Node<K,V> pred = e;

                                if ((e = e.next) == null) {

                                    pred.next = new Node<K,V>(hash, key,

                                                              value, null);

                                    break;

                                }

                            }

                        }

                        else if (f instanceof TreeBin) {

                            Node<K,V> p;

                            binCount = 2;

                            if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,

                                                           value)) != null) {

                                oldVal = p.val;

                                if (!onlyIfAbsent)

                                    p.val = value;

                            }

                        }

                    }

                }

                if (binCount != 0) {

                    if (binCount >= TREEIFY_THRESHOLD)

                        treeifyBin(tab, i);

                    if (oldVal != null)

                        return oldVal;

                    break;

                }

            }

        }

        addCount(1L, binCount);

        return null;

    }

 

使用synchronized (f)加锁保证并发安全性。减小锁的粒度,只对table中的一个对象加锁。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

三:get操作:获取table的时候使用tabAt方法,返回volatile对象保证操作的可见性。

 

public V get(Object key) {

        Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;

        int h = spread(key.hashCode());

        if ((tab = table) != null && (n = tab.length) > 0 &&

            (e = tabAt(tab, (n - 1) & h)) != null) {

            if ((eh = e.hash) == h) {

                if ((ek = e.key) == key || (ek != null && key.equals(ek)))

                    return e.val;

            }

            else if (eh < 0)

                return (p = e.find(h, key)) != null ? p.val : null;

            while ((e = e.next) != null) {

                if (e.hash == h &&

                    ((ek = e.key) == key || (ek != null && key.equals(ek))))

                    return e.val;

            }

        }

        return null;

    }

 

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);

   

 

 

 

四:size操作:使用counterCells保存有修改的时候修改这个数组,最后累加这个数组得到个数。

 

    private transient volatile CounterCell[]counterCells;

     /**

     * {@inheritDoc}

     */

    public int size() {

        long n = sumCount();

        return ((n < 0L) ? 0 :

                (n >(long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :

                (int)n);

    }

 

final long sumCount() {

        CounterCell[] as = counterCells;CounterCell a;

        long sum = baseCount;

        if (as != null) {

            for (int i = 0; i < as.length;++i) {

                if ((a = as[i]) != null)

                    sum += a.value;

            }

        }

        return sum;

    }

 

private final void addCount(long x, int check) {

        CounterCell[] as; long b, s;

        if ((as = counterCells) != null ||

            !U.compareAndSwapLong(this,BASECOUNT, b = baseCount, s = b + x)) {

            CounterCell a; long v; int m;

            boolean uncontended = true;

            if (as == null || (m = as.length -1) < 0 ||

                (a =as[ThreadLocalRandom.getProbe() & m]) == null ||

                !(uncontended =

                  U.compareAndSwapLong(a,CELLVALUE, v = a.value, v + x))) {

                fullAddCount(x, uncontended);

                return;

            }

            if (check <= 1)

                return;

            s = sumCount();

        }

        if (check >= 0) {

            Node<K,V>[] tab, nt; int n,sc;

            while (s >= (long)(sc = sizeCtl)&& (tab = table) != null &&

                   (n = tab.length) <MAXIMUM_CAPACITY) {

                int rs = resizeStamp(n);

                if (sc < 0) {

                    if ((sc >>>RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||

                        sc == rs + MAX_RESIZERS|| (nt = nextTable) == null ||

                        transferIndex <= 0)

                        break;

                    if(U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))

                        transfer(tab, nt);

                }

                else if(U.compareAndSwapInt(this, SIZECTL, sc,

                                            (rs << RESIZE_STAMP_SHIFT) + 2))

                    transfer(tab, null);

                s = sumCount();

            }

        }

    }

 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值