spring容器初始化遇到的死锁问题解决

所属分类: 软件编程 / java 阅读数: 24
收藏 0 赞 0 分享

前言

最近启动spring项目的时候遇到一个死锁问题,使用jstack获取线程堆栈的时候,可以看到2个线程出现了死锁:

解决过程:

DefaultSingletonBeanRegistry.getSingleton()源码如下,可以看到这个方法需要对singletonObjects加锁

第二处xxx.subject.core.cache.DataLocalcacheInit.afterPropertiesSet源码如下:

可以看到:这个bean在初始化的时候,会开启线程,调用另外一个bean的initData()方法从数据库加载数据。等数据加载完毕,DataLocalcacheInit这个bean的初始化才算完成。

通过上面的堆栈可以看出:spring容器在初始化bean的时候,会对singletonObjects对象加锁;我们自己在afterPropertiesSet()方法中开启了一个线程,最终也会触发spring加载另外的bean。第一个线程(初始化spring的main线程)还没有释放锁,第二个线程(自己开启的线程),也需要获取singletonObjects对象锁,这样就出现了死锁。表现出来的现象就是:spring容器卡在那里,不能完成所有bean的初始化。

来看一段例子,这个例子和我们项目中实际代码很相似。FirstBean调用ConfigHelper中的方法:

public class FirstBean implements InitializingBean {
 
 @Override
 public void afterPropertiesSet() throws Exception {
  System.out.println("first bean is initializing....");
 
  BlockingQueue queue = new ArrayBlockingQueue(10);
  Thread thread = new Thread() {
 
   @Override
   public void run() {
    ConfigHelper.doSomething();
    queue.add(1);
   }
  };
 
  thread.start();
 
  queue.take();
  System.out.println("first get data....");
 
 }
}

ConfigHelper代码如下:通过BeanFactory获取到另外一个bean

public class ConfigHelper implements BeanFactoryAware {
 private static BeanFactory factory;
 
 @Override
 public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  this.factory = beanFactory;
 }
 
 public static void doSomething()
 {
  SecondBean bean = (SecondBean)factory.getBean("second");
  bean.say();
 }
}

SecondBean代码很简单如下:

public class SecondBean {
 public void say() {
  System.out.println("SecondBean....");
 }
}

spring配置文件和启动代码如下,运行可以发现出现死锁:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
 
 
 <bean id="config" class="net.aty.spring.deadlock.ConfigHelper"></bean>
 <bean id="first" class="net.aty.spring.deadlock.FirstBean"></bean>
 <bean id="second" class="net.aty.spring.deadlock.SecondBean"></bean>
 
</beans>
public class Main {
 public static void main(String[] args) {
  ApplicationContext context = new FileSystemXmlApplicationContext(
    "src/main/java/net/aty/spring/deadlock/deadlock.xml");// 加载 spring 配置文件
 
 }
}

spring初始化的时候,如果我们在spring提供的一些扩展点处(BeanFactoryAware/InitializingBean等),开启线程去获取bean,很容器出现死锁。因为spring初始化单例bean(大多数bean都是单例的)会加锁。如果初始化1个bean的时候,还没有释放锁,另一个线程再次触发spring加载bean,就会出现死锁。

解决上面的问题很简单:FirstBean逻辑上是依赖于ConfigHelper和SecondBean的,但是我们却并没有显示地告诉spring这种逻辑关系。spring初始化FirstBean的时候,进入afterPropertiesSet() ,这个方法开启了线程会触发另外2个bean的加载。我们只要显示地告诉spring这种依赖关系,让spring先加载ConfigHelper和SecondBean就可以了。

<bean id="config" class="net.aty.spring.deadlock.ConfigHelper" depends-on="second"></bean>
<bean id="first" class="net.aty.spring.deadlock.FirstBean" depends-on="config"></bean>
<bean id="second" class="net.aty.spring.deadlock.SecondBean"></bean>

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

更多精彩内容其他人还在看

Java基础之反射原理与用法详解

这篇文章主要介绍了Java基础之反射原理与用法,结合实例形式详细分析了java反射的相关概念、原理、使用方法与操作注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

java字符串的截取方法substring()代码解析

这篇文章主要介绍了java字符串的截取方法substring()代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Mybatis一对多关联关系映射实现过程解析

这篇文章主要介绍了Mybatis一对多关联关系映射实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Java整数和字符串相互转化实例详解

这篇文章主要介绍了Java整数和字符串相互转化实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Spring Boot 项目设置网站图标的方法

这篇文章主要介绍了Spring Boot 项目设置网站图标的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

java多态机制原理特点详解

在本篇文章里小编给大家分享的是关于java多态机制原理特点详解,有需要的朋友们可以跟着学习下。
收藏 0 赞 0 分享

Jmeter如何添加循环控制器

这篇文章主要介绍了Jmeter如何添加循环控制器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

java虚拟机创建失败的原因整理

在本篇文章里小编给大家整理了关于创建java虚拟机失败的解决方法和知识点,需要的朋友们可以参考学习下。
收藏 0 赞 0 分享

Java如何把int类型转换成byte

这篇文章主要介绍了Java如何把int类型转换成byte,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

linux中java获取路径的实例代码

在本篇文章里小编给大家整理的是一篇关于linux中java获取路径的实例代码以及相关知识点,有兴趣的朋友们可以学习参考下。
收藏 0 赞 0 分享
查看更多