ConcurrentHashMap 的使用问题

2019-06-12 07:41:42 +08:00
 gramyang

昨天在 netty 的 handler 里碰到了一个非常奇怪的问题: 1、首先,handler 没有加 sharable 注解 2、我在 handler 的外部生成了一个 concurrenthashmap 实例并传入 handler 3、在 handler 的一个方法中调用 concurrenthashmap 的 remove(player.getNum()),然后再调用 player=null 将 player 清空。

这个时候奇迹出现了,remove 报空指针,也就是 remove 的时候 player 是 null。 我检查完了所有的代码,再没有其他地方把 player 设置为 null,并且 remove 的操作前还判断了 player!=null。

思来想去,只有两个可能: Java 中的指令重排序,导致 player 在 remove 之前就被空置,但是感觉不太可能啊。。。 concurrenthashmap 是多个线程共享的变量,直接 remove 会出现并发问题。。。

请大神指导!!

4197 次点击
所在节点    Java
29 条回复
gramyang
2019-06-12 10:19:33 +08:00
@xuanbg exitOrException 的第一个 remove
gramyang
2019-06-12 10:21:25 +08:00
@imzhoukunqiang 是的,很诡异。说实话,上面的代码已经是我修改过了的,不过意思没变,都是很诡异的空指针。
passerbytiny
2019-06-12 10:25:51 +08:00
去翻了一下 https://netty.io/4.0/api/io/netty/channel/ChannelHandler.Sharable.html,没有 Sharable 的时候,Handle 是单个通道独占的。

到目前为止,根据楼主已放出来的消息,找不出其他原因了。
gramyang
2019-06-12 10:31:59 +08:00
@passerbytiny 也足够了,起码帮助排除了重排序和并发错误的可能性。修改代码后如果再出现这种错误再另说
firefffffffffly
2019-06-12 10:41:50 +08:00
建议把 exception 信息贴出来,这样能轻松确定是 map 为空还是传入的 key 值为空。
从描述的 exception 来看 player 最不可能为空,因为这样的话报错 message 和 traces 里是不会包含 remove 相关内容的,因为在 player.getNum()时就会报错了,remove 函数还没有入栈。
key 值为空的情况,就是 player.getNum()的结果为 null,这个 player 内部属性需要再检查一下是否有多线程修改。
rainmakeroly
2019-06-12 10:44:57 +08:00
player 的获取,设置,初始化。报错信息的话主要是它吧
alamaya
2019-06-12 11:48:40 +08:00
你这个 apiHandler 是怎么来的?没看出来你的 player 是怎么传入的
senninha
2019-06-12 16:34:55 +08:00
- -player 在其他线程并发置 null 了?有其他线程在操作这个 player ?如果其他线程要操作,可以丢到 eventloop 里转成同步执行,保证并发安全。
ps:直接在 handler 里写业务代码的吗?这么强悍。。
laodao1990
2019-06-13 16:11:12 +08:00
要不这样试试:
if player!=null
锁{
if player!=null {
remove
}
}

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

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

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

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

© 2021 V2EX