HashMap在并发下的ArrayIndexOutOfBoundsException异常原因

悠树 发布于 2017/01/22 18:05
阅读 742
收藏 0

执行末尾的代码,有时会出现ArrayIndexOutOfBoundsException异常(下图),只有put和get操作,什么情况会出现这个异常?看源码没搞明白,求解。

public class TestLock {

    private HashMap map = new HashMap();

    public TestLock() {
        Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.put(new Integer(i), i);
                }
                System.out.println("t1 over");
            }
        };

        Thread t2 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.put(new Integer(i), i);
                }

                System.out.println("t2 over");
            }
        };

        Thread t3 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.put(new Integer(i), i);
                }

                System.out.println("t3 over");
            }
        };

        Thread t4 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.put(new Integer(i), i);
                }

                System.out.println("t4 over");
            }
        };

        Thread t5 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.put(new Integer(i), i);
                }

                System.out.println("t5 over");
            }
        };

        Thread t6 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.get(new Integer(i));
                }

                System.out.println("t6 over");
            }
        };

        Thread t7 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.get(new Integer(i));
                }

                System.out.println("t7 over");
            }
        };

        Thread t8 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.get(new Integer(i));
                }

                System.out.println("t8 over");
            }
        };

        Thread t9 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.get(new Integer(i));
                }

                System.out.println("t9 over");
            }
        };

        Thread t10 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    map.get(new Integer(i));
                }

                System.out.println("t10 over");
            }
        };

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();

        t6.start();
        t7.start();
        t8.start();
        t9.start();
        t10.start();
    }

    public static void main(String[] args) {
        new TestLock();
    }
}

 

加载中
2
lock_free
lock_free
就一点,hashmap不是线程安全的,不能并发使用
悠树
悠树
我没表达清楚,再开了个贴说明了下:https://www.oschina.net/question/555043_2218274
黔中伯爵
黔中伯爵
+2
tinshen
tinshen
+1 请用ConcurrentHashMap,线程安全。
1
爱吃荷包蛋i
爱吃荷包蛋i

没有死循环占用你100%cpu已经是客气的了

悠树
悠树
我没表达清楚,再开了个贴说明了下:https://www.oschina.net/question/555043_2218274
0
zigzagroad
zigzagroad
HashMap中有一个自动扩容的数组和当前索引值;当多个线程向该数组放入内容时,多个线程在“当时”都判断为 当前索引值没有超出当前数组大小,但领先的线程执行放入内容以后,当前索引值就会自动增长并且有可能超过数组大小,此时 下一个线程 再放入内容时就会报 数组索引超出范围的异常了。这就是“非线程安全”问题。多线程环境下应(根据业务要求决定是否)使用线程安全的对象类型。
zigzagroad
zigzagroad
理论上是放在了旧的数组上了,造成索引越界了;这种问题都是发生在毫秒或微秒级的时间粒度上,所以如果真的是这种需求的话,用具有同步锁功能的Map子类、或者在自己的程序中加上同步锁来控制一下相关操作。
悠树
悠树
是不是会出现按新table的长度计算出下标值后把数据放在旧table上?这样就会导致这个异常。
悠树
悠树
第301行代码 table[indexFor(hash, table.length)] 产生的异常,用到的就是table和table.length,扩容的时候table在增大,我能理解的就是会放错位置,比如按旧table的长度计算到下标值放在新table上,但不应该出现超出范围的,因为新table总是比旧table大。
0
dy810810
dy810810

引用来自“lock_free”的评论

就一点,hashmap不是线程安全的,不能并发使用

+1

0
兴百姓苦_亡百姓苦

这种问题毫无意义

悠树
悠树
我没表达清楚,再开了个贴说明了下:https://www.oschina.net/question/555043_2218274
0
大賢者
大賢者

 thread unsafe

返回顶部
顶部