V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
crossoverJie
V2EX  ›  程序员

一次 HashSet 所引起的并发问题

  •  4
     
  •   crossoverJie ·
    crossoverJie · 2018-11-09 12:56:00 +08:00 · 2753 次点击
    这是一个创建于 1992 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一次 HashSet 所引起的并发问题

    大家都在说的 HashMap 并发问题居然真碰上了🤣.

    18 条回复    2018-11-09 16:59:40 +08:00
    mortonnex
        1
    mortonnex  
       2018-11-09 13:22:45 +08:00 via iPhone
    点赞
    YAHIKO0
        2
    YAHIKO0  
       2018-11-09 13:28:04 +08:00
    d=====( ̄▽ ̄*)b
    crossoverJie
        3
    crossoverJie  
    OP
       2018-11-09 13:34:13 +08:00
    @YAHIKO0 #2

    兄弟你这颜表情是啥意思

    jy02201949
        4
    jy02201949  
       2018-11-09 13:35:04 +08:00
    @crossoverJie #3 智能送分机器人
    YAHIKO0
        5
    YAHIKO0  
       2018-11-09 13:35:38 +08:00
    点赞,
    @crossoverJie
    coolcfan
        6
    coolcfan  
       2018-11-09 13:55:25 +08:00 via Android
    可以直接 Collections.newSetFromMap(new ConcurrentHashMap ()),无缝替换掉,省掉手动写死 value
    crossoverJie
        7
    crossoverJie  
    OP
       2018-11-09 14:02:19 +08:00
    @coolcfan #6

    嗯 本质上原理是一样的。
    aimaodeyuer
        8
    aimaodeyuer  
       2018-11-09 14:17:20 +08:00
    追踪问题的能力还是要向大佬学习!
    amon
        9
    amon  
       2018-11-09 14:35:31 +08:00
    点赞,这个问题只是理论上听到过,还真没看到过,哈哈。
    Jokerrrrrr
        10
    Jokerrrrrr  
       2018-11-09 14:41:24 +08:00
    分析排查的,有点厉害
    Antidictator
        11
    Antidictator  
       2018-11-09 14:50:47 +08:00
    点赞+1
    TommyLemon
        12
    TommyLemon  
       2018-11-09 15:01:39 +08:00
    赞。
    我第一次看到 HashSet 的实现源码也震惊了,居然是用 HashMap 实现的,
    HashSet 里的所有 value 存到了 HashMap 里的所有 key,HashMap 的 value 则是全局的
    private static final Object PRESENT = new Object();
    文中用 ConcurrentHashMap 替代 HashSet 并写死 value 的做法,
    其实就是把 HashSet 简单地重新实现了一遍,并保证线程安全。
    TommyLemon
        13
    TommyLemon  
       2018-11-09 15:07:10 +08:00
    @TommyLemon 至于形成环形链表的原因我看到问题就猜出来是
    多线程并发执行
    set.add(key)
    时同一个 key 被添加多次,然后导致
    valueI = key
    valueJ = key
    当循环里通过
    value = value.next
    形成了从 valueI 到 valueJ 的环形链表
    BBCCBB
        14
    BBCCBB  
       2018-11-09 15:07:29 +08:00
    这..... 这难道不是常识吗?


    Collections.newSetFromMap(new ConcurrentHashMap<>())
    crossoverJie
        15
    crossoverJie  
    OP
       2018-11-09 15:48:33 +08:00
    @TommyLemon #12

    是的,所以把实现的时候简单封装个类就可以了。
    crossoverJie
        16
    crossoverJie  
    OP
       2018-11-09 15:49:52 +08:00
    @BBCCBB #14

    我确实是很少用 Collections.newSetFromMap 这个 API,有并发 set 要求都是用自己封装的 ConcurrentHashMap,不过原理都是一样的,不用过多纠结。
    x66
        17
    x66  
       2018-11-09 16:42:45 +08:00
    感觉 Set 是为了去重,感觉 Redis 更适合干这事。
    crossoverJie
        18
    crossoverJie  
    OP
       2018-11-09 16:59:40 +08:00
    @x66 #17

    Redis 当然可以。这本来就是个祖传代码,所以想最快的改造上线。

    加上其实我们的场景没必要用 Redis,就内存操作还更快。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   991 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:30 · PVG 04:30 · LAX 13:30 · JFK 16:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.