一次 HashSet 所引起的并发问题

2018 年 11 月 9 日
 crossoverJie

一次 HashSet 所引起的并发问题

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

3251 次点击
所在节点    程序员
18 条回复
mortonnex
2018 年 11 月 9 日
点赞
YAHIKO0
2018 年 11 月 9 日
d=====( ̄▽ ̄*)b
crossoverJie
2018 年 11 月 9 日
@YAHIKO0 #2

兄弟你这颜表情是啥意思

jy02201949
2018 年 11 月 9 日
@crossoverJie #3 智能送分机器人
YAHIKO0
2018 年 11 月 9 日
点赞,
@crossoverJie
coolcfan
2018 年 11 月 9 日
可以直接 Collections.newSetFromMap(new ConcurrentHashMap ()),无缝替换掉,省掉手动写死 value
crossoverJie
2018 年 11 月 9 日
@coolcfan #6

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


Collections.newSetFromMap(new ConcurrentHashMap<>())
crossoverJie
2018 年 11 月 9 日
@TommyLemon #12

是的,所以把实现的时候简单封装个类就可以了。
crossoverJie
2018 年 11 月 9 日
@BBCCBB #14

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

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

加上其实我们的场景没必要用 Redis,就内存操作还更快。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/506083

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX