ConcurrentHashMap源码学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable {
    final Segment<K,V>[] segments;
    static final int RETRIES_BEFORE_LOCK = 2;

    public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
        int sshift = 0;
        int ssize = 1;
        while (ssize < concurrencyLevel) {
            ++sshift;
            ssize <<= 1;
        }
        this.segmentShift = 32 - sshift;
        this.segmentMask = ssize - 1;
    }

    static final class HashEntry<K,V> {
        final int hash;
        final K key;
        volatile V value;
        volatile HashEntry<K,V> next;
    }

    private int hash(Object k) {
        int h = hashSeed;

        if ((0 != h) && (k instanceof String)) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();

        // Spread bits to regularize both segment and index locations,
        // using variant of single-word Wang/Jenkins hash.
        h += (h <<  15) ^ 0xffffcd7d;
        h ^= (h >>> 10);
        h += (h <<   3);
        h ^= (h >>>  6);
        h += (h <<   2) + (h << 14);
        return h ^ (h >>> 16);
    }

    static final class Segment<K,V> extends ReentrantLock implements Serializable {
        transient volatile HashEntry<K,V>[] table;
        transient int count;
        // modify count
        transient int modCount;
        transient int threshold;
        final float loadFactor;

        final V put(K key, int hash, V value, boolean onlyIfAbsent) {
            tryLock()
            // may rehash()
            unlock()
        }

        final V remove(Object key, int hash, Object value) {
            tryLock()
            unlock()
        }
    }

    public V get(Object key) {
        int h = hash(key);
        // Segment index
        (long)(((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE
        // Table index
        ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE
    }

    // Try RETRIES_BEFORE_LOCK times to get accurate count. On failure due to
    // continuous async changes in table, resort to LOCKING.    
    public int size() {
        // check segment.modCount to ensure accurate
        // but return sum of segment.count
    }

    public boolean isEmpty() {
        long sum = 0L;
        for (int j = 0; j < segments.length; ++j) {
            Segment<K,V> seg = segmentAt(segments, j);
            // if seg.count != 0, return false
            // else sum+=seg.modCount
        }

        // recheck unless no modifications
        for (int j = 0; j < segments.length; ++j) {
            //sum-=seg.modCount
        }
        if(sum != 0) return false;
        return true;
    }

    static {
        int ss, ts;
        UNSAFE = sun.misc.Unsafe.getUnsafe();
        Class tc = HashEntry[].class;
        Class sc = Segment[].class;
        TBASE = UNSAFE.arrayBaseOffset(tc);
        SBASE = UNSAFE.arrayBaseOffset(sc);
        ts = UNSAFE.arrayIndexScale(tc);
        ss = UNSAFE.arrayIndexScale(sc);
        SSHIFT = 31 - Integer.numberOfLeadingZeros(ss);
        TSHIFT = 31 - Integer.numberOfLeadingZeros(ts);
    }
}