一次 HashSet 所引起的并发问题

2018-11-09 12:56:00 +08:00
 crossoverJie

一次 HashSet 所引起的并发问题

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

2763 次点击
所在节点    程序员
18 条回复
mortonnex
2018-11-09 13:22:45 +08:00
点赞
YAHIKO0
2018-11-09 13:28:04 +08:00
d=====( ̄▽ ̄*)b
crossoverJie
2018-11-09 13:34:13 +08:00
@YAHIKO0 #2

兄弟你这颜表情是啥意思

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

嗯 本质上原理是一样的。
aimaodeyuer
2018-11-09 14:17:20 +08:00
追踪问题的能力还是要向大佬学习!
amon
2018-11-09 14:35:31 +08:00
点赞,这个问题只是理论上听到过,还真没看到过,哈哈。
Jokerrrrrr
2018-11-09 14:41:24 +08:00
分析排查的,有点厉害
Antidictator
2018-11-09 14:50:47 +08:00
点赞+1
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
2018-11-09 15:07:10 +08:00
@TommyLemon 至于形成环形链表的原因我看到问题就猜出来是
多线程并发执行
set.add(key)
时同一个 key 被添加多次,然后导致
valueI = key
valueJ = key
当循环里通过
value = value.next
形成了从 valueI 到 valueJ 的环形链表
BBCCBB
2018-11-09 15:07:29 +08:00
这..... 这难道不是常识吗?


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

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

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