当前位置:首页 > 科技  > 软件

警惕!SpringBoot错误发布事件,造成死锁Deadlock

来源: 责编: 时间:2024-06-12 08:43:40 262观看
导读环境:SpringBoot3.2.51. 死锁复现1.1 自定义事件监听public class PackApplicationEvent extends ApplicationEvent { private String message ; public PackApplicationEvent(String message, Object source) {

环境:SpringBoot3.2.5KeM28资讯网——每日最新资讯28at.com

1. 死锁复现

1.1 自定义事件监听

public class PackApplicationEvent extends ApplicationEvent {  private String message ;  public PackApplicationEvent(String message, Object source) {    super(source) ;    this.message = message ;  }  public String getMessage() {    return message ;  }}

自定义事件,接收消息及相关数据KeM28资讯网——每日最新资讯28at.com

1.2 自定义事件监听

@Componentpublic class PackApplicationListener implements ApplicationListener<PackApplicationEvent> {  @Override  public void onApplicationEvent(PackApplicationEvent event) {    System.out.printf("接收到事件消息: %s, 数据: %s%n", event.getMessage(), event.getSource().toString()) ;    // TODO  }}

该事件监听器只打印了信息。KeM28资讯网——每日最新资讯28at.com

1.3 发布事件

@Componentpublic class EventProcessor {  public EventProcessor(ApplicationEventPublisher eventPublisher) {    Thread t = new Thread(() -> {      eventPublisher.publishEvent(new PackApplicationEvent("自定义事件", EventProcessor.this));    });    t.start() ;    try {      System.out.println("线程启动,等待执行完成...") ;      t.join() ;    } catch (InterruptedException e) {      System.err.printf("线程中断: %s, 错误: %s%n", Thread.currentThread().getName(), e.getMessage()) ;    }  }}

该Bean在构造函数中新启一个线程发布事件,同时通过join方法等待线程执行完成。KeM28资讯网——每日最新资讯28at.com

上面的程序运行后,发现输出了上面的打印内容后应用没有继续运行。打印整个线程栈(通过jstack命令查看),如下:KeM28资讯网——每日最新资讯28at.com

图片图片KeM28资讯网——每日最新资讯28at.com

根据线程信息,main线程在创建EventProcessor对象时,会先持有DefaultSingletonBeanRegistry.singletonObjects这个ConcurrentHashMap对象锁接着创建EventProcessor对象实例,在调用该对象的构造函数时,启动新的线程Thread-1,该线程发布事件同时通过join方法等待T1这个线程完成,在发布事件时Spring容器会获取所有的ApplicationListener,此时就会又创建PackApplicationListener对象,创建该对象同样要获取singletonObjects锁对象,这样就造成了死锁。KeM28资讯网——每日最新资讯28at.com

主线程

图片图片KeM28资讯网——每日最新资讯28at.com

主线程创建EventProcessor对象。KeM28资讯网——每日最新资讯28at.com

Thread-1线程

图片图片KeM28资讯网——每日最新资讯28at.com

Thread-1线程获取容器中的ApplicationListener类型的bean,该过程将执行到如下步骤:KeM28资讯网——每日最新资讯28at.com

图片图片KeM28资讯网——每日最新资讯28at.com

main线程持有singletonObjects锁,Thread-1线程又期望获取到该锁,但是main线程还要等待Thread-1线程执行完成。这死锁了。KeM28资讯网——每日最新资讯28at.com

以上是对死锁的复现及原因进行了分析,接下来进行问题的解决。KeM28资讯网——每日最新资讯28at.com

2. 解决问题

2.1 解决方式1

不要在构造函数中发布事件,而是应该在所有的单例对象都创建完后再执行,也就是实现SmartInitializingSingleton接口,该接口对应的回调方法会在所有的单例bean都创建完以后执行,这样就不会再出现deadlock问题。KeM28资讯网——每日最新资讯28at.com

@Componentpublic class EventProcessor implements SmartInitializingSingleton {  private final ApplicationEventPublisher eventPublisher ;  public EventProcessor(ApplicationEventPublisher eventPublisher) {    this.eventPublisher = eventPublisher ;  }  @Override  public void afterSingletonsInstantiated() {    Thread t = new Thread(() -> {      eventPublisher.publishEvent(new PackApplicationEvent("自定义事件", EventProcessor.this));    });    t.start() ;    try {      t.join() ;    } catch (InterruptedException e) {      System.err.printf("线程中断: %s, 错误: %s%n", Thread.currentThread().getName(), e.getMessage()) ;    }  }}

这样改造后容器能正常的启动,同时事件也正常的发布&监听。KeM28资讯网——每日最新资讯28at.com

afterSingletonsInstantiated方法的调用在如下:KeM28资讯网——每日最新资讯28at.com

public class DefaultListableBeanFactory {  public void preInstantiateSingletons() {    for (String beanName : beanNames) {      // 创建单例bean      getBean(beanName);    }    // 单例bean创建完成以后,执行afterSingletonsInstantiated回调方法    for (String beanName : beanNames) {      Object singletonInstance = getSingleton(beanName);      if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {        smartSingleton.afterSingletonsInstantiated();      }    }  }}

以上就不会在出现锁问题。KeM28资讯网——每日最新资讯28at.com

2.2 解决方式2

升级Spring版本到Spring6.2(目前并没有正式发布),你仍然可以使用6.2.0-SNAPSHOT版本,该版本通过多线程方式初始化Bean对象,这样就不会出现deadlock问题。KeM28资讯网——每日最新资讯28at.com


KeM28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-93206-0.html警惕!SpringBoot错误发布事件,造成死锁Deadlock

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 聊聊 Mybatis 动态 SQL

下一篇: 网易面试:SpringBoot如何开启虚拟线程?

标签:
  • 热门焦点
  • Mate60手机壳曝光 致敬自己的经典设计

    8月3日消息,今天下午博主数码闲聊站带来了华为Mate60的第三方手机壳图,可以让我们在真机发布之前看看这款华为全新旗舰的大致轮廓。从曝光的图片看,Mate 60背后摄像头面积依然
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • CSS单标签实现转转logo

    转转品牌升级后更新了全新的Logo,今天我们用纯CSS来实现转转的新Logo,为了有一定的挑战性,这里我们只使用一个标签实现,将最大化的使用CSS能力完成Logo的绘制与动画效果。新logo
  • Automa-通过连接块来自动化你的浏览器

    1、前言通过浏览器插件可实现自动化脚本的录制与编写,具有代表性的工具就是:Selenium IDE、Katalon Recorder,对于简单的业务来说可快速实现自动化的上手工作。Selenium IDEKat
  • 分享六款相见恨晚的PPT模版网站, 祝你做出精美的PPT!

    1、OfficePLUSOfficePLUS网站旨在为全球Office用户提供丰富的高品质原创PPT模板、实用文档、数据图表及个性化定制服务。优点:OfficePLUS是微软官方网站,囊括PPT模板、Word模
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 认真聊聊东方甄选:如何告别低垂的果实

    来源:山核桃作者:财经无忌爆火一年后,俞敏洪和他的东方甄选依旧是颇受外界关心的&ldquo;网红&rdquo;。7月5日至9日,为期5天的东方甄选&ldquo;甘肃行&rdquo;首次在自有App内直播,
  • onebot M24巧系列一体机采用轻薄机身设计,现已在各平台开售

    onebot M24 巧系列一体机目前已在线上线下各平台同步开售。onebot M24 巧系列采用一体化轻薄机身设计,最薄处为 10.15mm,拥有宝石红、午夜蓝、石墨绿、雅致
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top