美文网首页程序员
hashmap在多线程下的问题

hashmap在多线程下的问题

作者: justlinzhihe | 来源:发表于2018-01-31 18:33 被阅读0次

源码阅读请参考HashMap-jdk1.7

假设有两个线程T1,T2

1.漏值

    void createEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];//1
        table[bucketIndex] = new Entry<>(hash, key, value, e);
        size++;
    }

假设T1和T2的key哈希散列值一样,当T1执行到1处,cpu时间片切换,T2开始执行并且执行完整个createEntry,单当cpu时间片切回T1,那么这时候T1的值就会覆盖掉T2的值,造成T2的值消失了。

2.死循环

这个发生在数组扩容的时候。先看关键代码。

    void transfer(Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
        for (Entry<K,V> e : table) {
            while(null != e) {
                Entry<K,V> next = e.next;//1
                if (rehash) {
                    e.hash = null == e.key ? 0 : hash(e.key);
                }
                int i = indexFor(e.hash, newCapacity);
                e.next = newTable[i];
                newTable[i] = e;
                e = next;
            }
        }
    }

假设

table[3]=a; a.next=b; b.next=null;

T1,T2进行put的时候都发生了扩容,T1先执行,到1的地方cpu切换,此时对于T1来讲

e=a;next=b;

接下来T2执行并且执行完整个流程,那么此时对于这个hashmap来讲

table[3]=b; b.next=a; a.next=null;

cpu切回T1,执行第一遍循环

a.next=newtable[3]=null; newtable[3]=a; e=next=b;

结果就是

newtable[3]=a; a.next=null; table[3]=b; b.next=a;

执行第二遍循环

e=b; next=b.next=a;
b.next=newtable[3]=a; newtable[3]=b;e=a;

newtable[3]=b; b.next=a; a.next=null;

执行第三遍循环

e=a;next=null;
a.next=newtavle[3]=b; newtable[3]=a;e=null;

newtable[3]=b; b.next=a ; a.next=b;

等T1执行完table=newtable,下次遍历链表操作的时候就会发生死循环。

相关文章

网友评论

    本文标题:hashmap在多线程下的问题

    本文链接:https://www.haomeiwen.com/subject/agdlzxtx.html