抱歉,能帮忙举个简单的例子说明下HashMap在多线程环境中可以出现的put和get的bug吗?
如果我在多线程环境中同步HashMap的put操作而不同步get操作应该会比HashTable和Collections.synchronizedMap效率高吧,不知道这样做get出的对象有否问题?

解决方案 »

  1.   

    HashTable
    public synchronized V get(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
        if ((e.hash == hash) && e.key.equals(key)) {
    return e.value;
        }
    }
    return null;
        }HashMap
        public V get(Object key) {
            if (key == null)
                return getForNullKey();
            int hash = hash(key.hashCode());
            for (Entry<K,V> e = table[indexFor(hash, table.length)];
                 e != null;
                 e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                    return e.value;
            }
            return null;
        }
    仅从代码看,没看到明显的会产生不同步的地方。但是,如果你在读取得时候,在put那面把你正好要的那个key/value给删除了,你猜会发生什么事情??
    也就是恰恰在return前,刚好被删掉了!而Hashtable 会保证那面put完毕,这面才会get,反之,我在get的时候,那面put要等。
      

  2.   

    感谢java2000_net 的回答,你说得很好。请允许我迟些结帖,我还想请教下:
    java2000_net 在楼上说到“在put那面把你正好要的那个key/value给删除了 ”是指put操作恰覆盖了我正要get的出来的 值 吗?如果我的程序中并不存在对HashMap的remove操作,且put操作修改的键值关联也并不影响业务结果(实际上put操作每次对应同一个键的关联值都相同,即值会是同一个object),我是否可以不同步get 操作?
      

  3.   

    比如那个循环,本来有100个,你在操作到99的时候,不巧,另一面put了一个,变成了101个,如果删掉了10个,你就更惨了。这时候会发生同步异常的。CurrencyException, 当然,也许你不是那么惨,每次都碰上。不过,我一般还是用HashMap的,只是自己使用的时候注意点就行了。
      

  4.   

    我觉得get同不同步无所谓 最关键是get和put之间的一个同步 可能会影响get取值的精准性 其次是put的同步 保证有效性
      

  5.   


    有道理,键值在对象表中的位置与table.length有关系。
      

  6.   

    “如果我的程序中并不存在对HashMap的remove操作,且put操作修改的键值关联也并不影响业务结果(实际上put操作每次对应同一个键的关联值都相同,即值会是同一个object),我是否可以不同步get 操作?”上几楼我这么说说明我没充分理解不同步会对get的精确度产生的影响。也正如dracularking 所述:

    我觉得get同不同步无所谓 最关键是get和put之间的一个同步 可能会影响get取值的精准性 其次是put的同步 保证有效性

    感谢二位。
    我再去学习下“同步异常”CurrencyException,还想再讨论下这个“同步异常”,不过还是结帖送分先。