时间:2021-05-19
前言
最近启动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
SecondBean代码很简单如下:
spring配置文件和启动代码如下,运行可以发现出现死锁:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://.aty.spring.deadlock.SecondBean"></bean>总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
MyBatis初始化过程就是生成一些必须的对象放到Spring容器中。问题是这个过程到底生成了哪些对象?当遇到MyBatis初始化失败时,如何正确的找到分析问题
Java线程死锁的问题解决办法【线程死锁】原因:两个线程相互等待被对方锁定的资源代码模拟:publicclassDeadLock{publicstaticvoi
关于在spring容器初始化bean和销毁前所做的操作定义方式有三种:第一种:通过注解@PostConstruct和@PreDestroy方法实现初始化和销毁b
前言首先我们初始化一个最简单的容器,用这个容器研究初始化的流程。下面就是一个再简单不过的IoC容器了,该容器包含了一个名为beanA的bean,我们初始化容器后
这篇文章主要介绍了Spring关闭TomcatServlet容器时内存泄漏问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价