默认
发表评论 21
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
[已回复] 求助关于MobileIMSDK服务端单例模式并发安全问题
bug:mobileSDK 大量使用了单例模式,但是并没有双重效验机制,今天正好碰到了这个并发问题,导致在线用户某一时刻同时上线出现的bug;
望作者修改!

示例:
public static OnlineProcessor getInstance() {
    if (instance == null)
        instance = new OnlineProcessor();
    return instance;
}

//优化后public static OnlineProcessor getInstance() {
    if (instance == null) {
        synchronized (OnlineProcessor.class) {
            if (instance == null) {
                instance = new OnlineProcessor();
            }
        }
    }
    return instance;
}

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:开源轻量级IM框架 MobileIMSDK v6.1 已发布!下一篇:[已回复] 求教关于MobileIMSDK里传送较大量数据的疑问

本帖已收录至以下技术专辑

推荐方案
评论 21
你具体描述一下:“导致在线用户某一时刻同时上线出现的bug”?

另外,你这样粗暴的 synchronized,肯定会影响性能。你描述一下现象,我来分析一下,看看是否新版代码存在隐患。

引用:JackJiang 发表于 2021-08-02 11:09
你具体描述一下:“导致在线用户某一时刻同时上线出现的bug”?

另外,你这样粗暴的 synchronized,肯定 ...

场景:1 两个客户端登录成功,2 服务端下线,客户端自动登录启动,3 启动服务端,两个客户端同时登录,由于netty下的异步响应有几率导致两个获取的instance 不一致,我通过输出hashcode发现的不一致,目前只在第一次启动的时候出现这样的问题。
引用:要你命三千 发表于 2021-08-02 11:37
场景:1 两个客户端登录成功,2 服务端下线,客户端自动登录启动,3 启动服务端,两个客户端同时登录,由 ...

instance 不一致?

你指的是出现了两个不同的OnlineProcessor实例?
引用:JackJiang 发表于 2021-08-02 11:52
instance 不一致?

你指的是出现了两个不同的OnlineProcessor实例?


两上实例肯定不对的,你排查一下,为什么会搞出两个实例。你服务端是怎么部署的,放在Spring boot里的吗,我记得之前有人Spring boot里bean没用明白,就重复实例了
引用:JackJiang 发表于 2021-08-02 12:20
两上实例肯定不对的,你排查一下,为什么会搞出两个实例。你服务端是怎么部署的,放在Spring boot里的吗 ...

调试的是作者源码,作者的demo

07906829-D0B6-432c-AFF5-9FF94DDB1F0sssssssss5.png (922.78 KB, 下载次数: 2802)

07906829-D0B6-432c-AFF5-9FF94DDB1F0sssssssss5.png
引用:JackJiang 发表于 2021-08-02 12:20
两上实例肯定不对的,你排查一下,为什么会搞出两个实例。你服务端是怎么部署的,放在Spring boot里的吗 ...

问题就在于两个客户端在服务端启动的一瞬间上线了,同时调用OnlineProcessor的getInstance()方法导致的并发 问题
引用:要你命三千 发表于 2021-08-02 14:16
问题就在于两个客户端在服务端启动的一瞬间上线了,同时调用OnlineProcessor的getInstance()方法导致的 ...

别说2个客户端,200个我都刻意试过,没遇到过你说的情况。你的JDK用的是什么版本?
引用:要你命三千 发表于 2021-08-02 14:16
问题就在于两个客户端在服务端启动的一瞬间上线了,同时调用OnlineProcessor的getInstance()方法导致的 ...

你上面回复了好几贴,我还是没弄明白你说的并发问题,具体是什么问题?我说蒙逼了。。。
你说的两个实例,这个截图上貌似也没看出来什么并发问题或者你说的两个实例

或者我没有理解你的意思?
引用:JackJiang 发表于 2021-08-02 14:23
你上面回复了好几贴,我还是没弄明白你说的并发问题,具体是什么问题?我说蒙逼了。。。
你说的两个实例 ...

jdk11

把JDK降到1.8后,你看看效果,你现在就去试试
引用:JackJiang 发表于 2021-08-02 14:48
把JDK降到1.8后,你看看效果,你现在就去试试

现在在工作,而且目前没有jdk8的环境,我安找我发布的贴的优化后解决了这个问题,所以现在是测试不了了,而且我觉得这样的单例模式在jdk8下也会出现线程安全问题。
引用:JackJiang 发表于 2021-08-02 11:09
你具体描述一下:“导致在线用户某一时刻同时上线出现的bug”?

另外,你这样粗暴的 synchronized,肯定 ...

我觉得没有问题呀,synchronized只是在第一次 为null的时候才会有效啊,所以好像不会影响什么问题吧?还是我没理解到?
引用:要你命三千 发表于 2021-08-02 14:50
现在在工作,而且目前没有jdk8的环境,我安找我发布的贴的优化后解决了这个问题,所以现在是测试不了了, ...

你说的也有道理,我接受你的建议。因为目前为止主流一直都是jdk1.8,且经过大量使用确实没有出现过你说的情况,所以一直也没有在意这个,但不能排除更高版本的jdk有可能调用机制有变化,我会记录一下,持续关注这个问题。
引用:JackJiang 发表于 2021-08-02 14:54
你说的也有道理,我接受你的建议。因为目前为止主流一直都是jdk1.8,且经过大量使用确实没有出现过你说的 ...

    //之前的代码
    private static OnlineProcessor instance = null;
    //改为
    private static OnlineProcessor instance = new OnlineProcessor();
  这样也是可以的
引用:JackJiang 发表于 2021-08-02 14:54
你说的也有道理,我接受你的建议。因为目前为止主流一直都是jdk1.8,且经过大量使用确实没有出现过你说的 ...

我建议作者自己可以试一下
引用:JackJiang 发表于 2021-08-02 14:54
你说的也有道理,我接受你的建议。因为目前为止主流一直都是jdk1.8,且经过大量使用确实没有出现过你说的 ...

具体的流程就在上面我回复的第一帖,有个场景....
引用:要你命三千 发表于 2021-08-02 15:04
我建议作者自己可以试一下

理论上确实有可能出现你说的情况,但奇怪的是,这么多年更新以来,在JDK1.8及以下的版本中,从未发生过问题,一直工作的好好的。。。 这也导致我一直没把它当回事。
引用:JackJiang 发表于 2021-08-02 11:09
你具体描述一下:“导致在线用户某一时刻同时上线出现的bug”?

另外,你这样粗暴的 synchronized,肯定 ...

楼主的写法只会第一次初始化 OnlineProcessor 时加锁,应该没有多大性能开销,但是会不会出现指令重排的问题,导致调用时空指针。要不要加个volatile禁止指令重排   private volatile static OnlineProcessor instance
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部