• 请不要在回答技术问题时复制粘贴 AI 生成的内容
crossoverJie
V2EX  ›  程序员

一次 HashSet 所引起的并发问题

  •  4
     
  •   crossoverJie ·
    crossoverJie · Nov 9, 2018 · 3723 views
    This topic created in 2916 days ago, the information mentioned may be changed or developed.

    一次 HashSet 所引起的并发问题

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

    18 replies  •  2018-11-09 16:59:40 +08:00
    mortonnex
    mortonnex
    Nov 9, 2018 via iPhone
    1
    点赞
    YAHIKO0
    YAHIKO0
    Nov 9, 2018
    2
    d=====( ̄▽ ̄*)b
    crossoverJie
    crossoverJie
    OP
    Nov 9, 2018
    3
    @YAHIKO0 #2

    兄弟你这颜表情是啥意思

    jy02201949
    jy02201949
    Nov 9, 2018
    4
    @crossoverJie #3 智能送分机器人
    YAHIKO0
    YAHIKO0
    Nov 9, 2018
    5
    点赞,
    @crossoverJie
    coolcfan
    coolcfan
    Nov 9, 2018 via Android
    6
    可以直接 Collections.newSetFromMap(new ConcurrentHashMap ()),无缝替换掉,省掉手动写死 value
    crossoverJie
    crossoverJie
    OP
    Nov 9, 2018
    7
    @coolcfan #6

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


    Collections.newSetFromMap(new ConcurrentHashMap<>())
    crossoverJie
    crossoverJie
    OP
    Nov 9, 2018
    15
    @TommyLemon #12

    是的,所以把实现的时候简单封装个类就可以了。
    crossoverJie
    crossoverJie
    OP
    Nov 9, 2018
    16
    @BBCCBB #14

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

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

    加上其实我们的场景没必要用 Redis,就内存操作还更快。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3130 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 70ms · UTC 11:00 · PVG 19:00 · LAX 03:00 · JFK 06:00
    ♥ Do have faith in what you're doing.