HashMap 多线程问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
final0pro
V2EX    问与答

HashMap 多线程问题

  •  
  •   final0pro 2015-08-04 02:35:02 +08:00 3456 次点击
    这是一个创建于 3791 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个hashmap,多个线程访问

    一个读线程调用hashMap.get("xx")

    一个写线程重新赋值 hashMap = new HashMap()

    会不会出现问题?

    比如读的过程刚拿到key哈希之后的值,这个时候另一个线程重新assign了一个新的hashmap,这个理论上是会出问题的吧?

    写了几个测试,都pass了,但是感觉不靠谱啊。

    求指点。谢谢。

    18 条回复    2016-08-09 23:28:25 +08:00
    Valyrian
        1
    Valyrian  
       2015-08-04 03:04:19 +08:00 via iPhone
    ConcurrentHashMap
    final0pro
        2
    final0pro  
    OP
       2015-08-04 03:53:24 +08:00
    @Valyrian 对,这个肯定可以。

    但是我是想确定下,这种情况用hashmap会不会出现问题,出现什么样的问题?

    一般hashmap并发出现死循环,是因为二个线程同时在rehash同一个hashmap

    但是我的这种情况,一个只是get,永远不会rehash整个hashmap,所以应该不会出现死循环吧
    introom
        3
    introom  
       2015-08-04 04:29:48 +08:00
    @final0pro 最不理解这种回答完全和问题不相关的,这个感情是对问题的侮辱啊
    final0pro
        4
    final0pro  
    OP
       2015-08-04 04:47:56 +08:00
    @introom T_T
    Andiry
        5
    Andiry  
       2015-08-04 05:01:11 +08:00
    我不认为有啥问题,因为hashmap的reassign是原子的
    除非hashmap.get()当中又使用了hashmap本身
    final0pro
        6
    final0pro  
    OP
       2015-08-04 05:13:22 +08:00
    @Andiry google了一下,assignment好像不是原子的

    http://coolshell.cn/articles/265.html

    ```
    主要在于singleton = new Singleton()这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情。

    给 singleton 分配内存
    调用 Singleton 的构造函数来初始化成员变量,形成实例
    将singleton对象指向分配的内存空间(执行完这步 singleton才是非 null 了)
    ```

    那这样,岂不是有可能会NullPointerException。。。null.get("xx")了。。。
    Andiry
        7
    Andiry  
       2015-08-04 05:35:50 +08:00
    @final0pro 只要这三步按照顺序来就没问题,因为第三步是原子的,get线程永远不会看到NULL
    当然像那篇文章里说的重排序就挂了
    final0pro
        8
    final0pro  
    OP
       2015-08-04 05:50:53 +08:00
    @Andiry 除了这种情况,会不会还有另外一种可能?:

    thread1: get --》 拿到hash(key)的值 -》 线程被挂起

    thread2: reassign了新的hashmap

    thread1:被唤醒,因为之前已经拿到hash(key)了,所以继续拿这个去array中找,但是key这个时候可能已经全被打乱了

    感觉是有这个可能的,但是要在极度高并发的情况才有可能?
    Andiry
        9
    Andiry  
       2015-08-04 05:59:44 +08:00   1
    @final0pro 不会。即使thread2 reassign了hashmap,get访问的hashmap仍然是旧的那一个。除非旧hashmap在这个get过程当中被GC了。
    qiyi
        10
    qiyi  
       2015-08-04 06:51:02 +08:00 via iPhone   1
    hashMap要么是旧的Map要么是新的Map ,没啥问题,copyonwritehashmap就这么实现
    final0pro
        11
    final0pro  
    OP
       2015-08-04 08:04:28 +08:00
    @Andiry 懂了。谢谢!
    SoloCompany
        12
    SoloCompany  
       2015-08-04 08:45:12 +08:00 via iPhone
    加 violite 关键字
    laipogo
        13
    laipogo  
       2015-08-04 09:04:52 +08:00
    @SoloCompany
    volatile
    mind3x
        14
    mind3x  
       2015-08-04 09:47:52 +08:00 via Android   2
    @Andiry @qiyi 知道为什么 double checked locking 是错的吗?这里也是一样有 memory reordering 的问题,除非显式插入 barrier 保证顺序。

    @final0pro 建议阅读老文 http://www.javaworld.com/article/2074979/java-concurrency/double-checked-locking--clever--but-broken.html
    final0pro
        15
    final0pro  
    OP
       2015-08-04 23:33:43 +08:00
    @mind3x 学习了

    但是这篇文章是2001年,java1.5诞生之前

    根据http://coolshell.cn/articles/265.html这篇,

    ```
    但是,这个事情仅在Java 1.5版后有用,1.5版之前用这个变量也有问题,因为老版本的Java的内存模型是有缺陷的。
    ```

    现在应该没问题了
    qiyi
        16
    qiyi  
       2015-08-05 02:17:54 +08:00 via iPhone
    @mind3x 确实,应该添加volarile 关键字,感谢。
    qiyi
        17
    qiyi  
       2015-08-05 02:19:25 +08:00 via iPhone
    手机打字,纠正上面单词错误 ,volatile
    Karlllll
        18
    Karlllll  
       2016-08-09 23:28:25 +08:00
    题主,你的问题好像。。。。。
    get 访问跟你重新把一个指针指向一个新的 hashMap ,没有关系。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2517 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 11:31 PVG 19:31 LAX 03:31 JFK 06:31
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86