HashMap 多线程问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
final0pro

HashMap 多线程问题

  •  
  •   final0pro Aug 4, 2015 3662 views
    This topic created in 3923 days ago, the information mentioned may be changed or developed.

    一个hashmap,多个线程访问

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

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

    会不会出现问题?

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

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

    求指点。谢谢。

    18 replies    2016-08-09 23:28:25 +08:00
    Valyrian
        1
    Valyrian  
       Aug 4, 2015 via iPhone
    ConcurrentHashMap
    final0pro
        2
    final0pro  
    OP
       Aug 4, 2015
    @Valyrian 对,这个肯定可以。

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

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

    但是我的这种情况,一个只是get,永远不会rehash整个hashmap,所以应该不会出现死循环吧
    introom
        3
    introom  
       Aug 4, 2015
    @final0pro 最不理解这种回答完全和问题不相关的,这个感情是对问题的侮辱啊
    final0pro
        4
    final0pro  
    OP
       Aug 4, 2015
    @introom T_T
    Andiry
        5
    Andiry  
       Aug 4, 2015
    我不认为有啥问题,因为hashmap的reassign是原子的
    除非hashmap.get()当中又使用了hashmap本身
    final0pro
        6
    final0pro  
    OP
       Aug 4, 2015
    @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  
       Aug 4, 2015
    @final0pro 只要这三步按照顺序来就没问题,因为第三步是原子的,get线程永远不会看到NULL
    当然像那篇文章里说的重排序就挂了
    final0pro
        8
    final0pro  
    OP
       Aug 4, 2015
    @Andiry 除了这种情况,会不会还有另外一种可能?:

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

    thread2: reassign了新的hashmap

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

    感觉是有这个可能的,但是要在极度高并发的情况才有可能?
    Andiry
        9
    Andiry  
       Aug 4, 2015   1
    @final0pro 不会。即使thread2 reassign了hashmap,get访问的hashmap仍然是旧的那一个。除非旧hashmap在这个get过程当中被GC了。
    qiyi
        10
    qiyi  
       Aug 4, 2015 via iPhone   1
    hashMap要么是旧的Map要么是新的Map ,没啥问题,copyonwritehashmap就这么实现
    final0pro
        11
    final0pro  
    OP
       Aug 4, 2015
    @Andiry 懂了。谢谢!
    SoloCompany
        12
    SoloCompany  
       Aug 4, 2015 via iPhone
    加 violite 关键字
    laipogo
        13
    laipogo  
       Aug 4, 2015
    @SoloCompany
    volatile
    mind3x
        14
    mind3x  
       Aug 4, 2015 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
       Aug 4, 2015
    @mind3x 学习了

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

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

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

    现在应该没问题了
    qiyi
        16
    qiyi  
       Aug 5, 2015 via iPhone
    @mind3x 确实,应该添加volarile 关键字,感谢。
    qiyi
        17
    qiyi  
       Aug 5, 2015 via iPhone
    手机打字,纠正上面单词错误 ,volatile
    Karlllll
        18
    Karlllll  
       Aug 9, 2016
    题主,你的问题好像。。。。。
    get 访问跟你重新把一个指针指向一个新的 hashMap ,没有关系。
    About     Help     Advertise     Blog     API     FAQ     Solana     859 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 42ms UTC 22:03 PVG 06:03 LAX 15:03 JFK 18:03
    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