`

spring启动的时候尝试多线程发生的死锁

 
阅读更多
具体的死锁线程dump:
Found one Java-level deadlock:
=============================
"pool-3-thread-1":
  waiting to lock monitor 0x000000000aeaad68 (object 0x0000000780ffcf28, a java.util.concurrent.ConcurrentHashMap),
  which is held by "main"
"main":
  waiting to lock monitor 0x000000000aeaaeb8 (object 0x0000000780ff4a30, a java.util.concurrent.ConcurrentHashMap),
  which is held by "pool-3-thread-1"

Java stack information for the threads listed above:
===================================================
"pool-3-thread-1":
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinitionNames(DefaultListableBeanFactory.java:297)
	- waiting to lock <0x0000000780ffcf28> (a java.util.concurrent.ConcurrentHashMap)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:329)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:307)
	at org.springframework.context.support.AbstractApplicationContext.getBeanNamesForType(AbstractApplicationContext.java:1155)
	at com.my9yu.common.resource.reader.ReaderHolder.initialize(ReaderHolder.java:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:346)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:299)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:132)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1448)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
	- locked <0x0000000780ff4a30> (a java.util.concurrent.ConcurrentHashMap)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:876)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:818)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:286)
	at com.my9yu.common.resource.StorageManager.initializeStorage(StorageManager.java:118)
	at com.my9yu.common.resource.StorageManager.initialize(StorageManager.java:46)
	at com.my9yu.common.resource.StorageManagerFactory$StorageRunner.call(StorageManagerFactory.java:50)
	at com.my9yu.common.resource.StorageManagerFactory$StorageRunner.call(StorageManagerFactory.java:1)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
"main":
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:183)
	- waiting to lock <0x0000000780ff4a30> (a java.util.concurrent.ConcurrentHashMap)
	at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:882)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:590)
	- locked <0x0000000780ffcf28> (a java.util.concurrent.ConcurrentHashMap)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
	- locked <0x0000000780fd7bb0> (a java.lang.Object)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at com.eyu.ahxy.Main.main(Main.java:21)

Found 1 deadlock.



死锁发生的场景,我用多线程去createBean:
AutowireCapableBeanFactory beanFactory = this.applicationContext.getAutowireCapableBeanFactory();
		Storage storage = beanFactory.createBean(Storage.class);


而启动的主线程恰好执行refresh。

产生的原因是:DefaultListableBeanFactory和DefaultSingletonBeanRegistry的好些方法都是锁的一个字段(就是一个map),这样一交叉,就出现死锁了。
我在想DefaultListableBeanFactory和DefaultSingletonBeanRegistry的那些方法都是说对象自己的话,不就不会死锁了吗。
spring为什么要锁这么小的粒度?这不是逼着人单线程去执行这些事情吗?



ps:我使用的版本是3.1.2,我在网上看到说这个是spring3.1.4之前的bug。。。。
我看了下spring3.2.4的代码确实有点不一样:在DefaultSingletonBeanRegistry修改了下防止出现死锁

	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {



ps:从这篇文章可以看到具体的死锁原因:
http://blog.csdn.net/u013536492/article/details/23935439

过程一: spring 容器初始化

Spring 容器初始化的时候会实例化所有单例对象( preInstantiateSingletons ),这个过程中会对上面两个对象加锁,以防止并发。先对 beanDefinitionMap 加锁,防止元数据被修改,然后在每次实例化单例对象的时候对 singletonObjects 加锁,防止并发修改。

过程二:根据 spring 容器获取一个单例对象。

调用 spring 容器的 context.getBean ( beanName ),如果该 bean 是单例且还未实例化,这个时候就需要进行实例化,如果该 bean 直接或间接存在注解方式的 bean 注入的时候,过程中也会对以上两个对象进行加锁防止并发。先对 singleObjects 加锁,从改 map 里找是否有存在 beanName 的对象,没有的话在创建该 bean 的过程中会对 beanDefinitionMap 加锁。



可以看出以上过程一和过程二对两个对象的锁顺序是不一致的,所以并发执行就可能会发生死锁。

我是觉得:最本质的原因是spring在get的时候发现没有,就会去创建一个,get的方法却做了set的事情,这个是原因所在。
0
1
分享到:
评论

相关推荐

    java面试笔试资料包括JAVA基础核心知识点深度学习Spring面试题等资料合集.zip

    线程死锁及解决办法.docx 线程锁之重入锁.docx 线程间的通信.docx 虚拟机内存结构和垃圾回收docx.docx 锁分类的了解.docx 集合的扩容机制.png SpringMVC部分.docx Spring部分.docx 第一题.pdf 第七题 谈谈MySQL支持...

    2023Java高频面试题

    多线程编程:线程的基本概念、线程同步、线程安全、死锁等问题。 JDBC:Java与数据库的交互,连接池的使用等。 Spring框架:Spring框架的基础概念、IOC容器、AOP等。 Hibernate框架:Hibernate框架的基础概念、ORM...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    多线程put的时候可能导致元素丢失 68 解决方案 68 【集合】ConcurrentHashMap的get(),put(),又是如何实现的?ConcurrentHashMap有哪些问题?ConcurrentHashMap的锁是读锁还是写锁? 69 【集合】HashMap与HashTable...

    阿里百度美团面试题合集

    数据结构与算法:最常见的各种排序,最好能手写 .. Java 高级:JVM 内存结构、垃圾回收器、回收算法...多线程状态图,状态如何流转? . 死锁,死锁原因 . 页锁、乐观锁、悲观锁? . 乐观锁如何保证线程安全? . 用过线

    leetcode下载-JavaTopic:Java面试题总结

    leetcode下载 Spring篇: spring为什么是单实例的?有什么好处? spring单实例如何解决有状态bean的线程安全问题的? ThreadLocal的原理? spring事务7种传播特性和隔离级别的理解?...多线程死锁如何排查(考察linux

    Java常见面试题208道.docx

    面试题包括以下十九部分:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql...

    java7hashmap源码-springcloud-one:第一个自搭建微服务

    springcloud-one 面试准备项目 一、基础面试问答 _谈谈HashMap_ HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干 ...

    以下是一些常见的JAVA面试题

    4. 解释一下JAVA中的多线程编程,包括线程的生命周期、同步和死锁等问题。 5. 解释一下JAVA中的集合框架,包括List、Set、Map等接口和实现类的使用。 6. 解释一下JAVA中的泛型编程,包括泛型类型参数、通配符等的...

    史上最全java面试,103项重点知识,带目录

    三、多线程 13 35. 并行和并发有什么区别? 13 36. 线程和进程的区别? 14 37. 守护线程是什么? 14 38. 创建线程有哪几种方式? 14 39. 说一下 runnable 和 callable 有什么区别? 15 40. 线程有哪些状态? 15 41. ...

    springboot_mongodb

    高级多线程控制类 ThreadLocal类1个每个线程本地只能保存一个变量副本,如果想要上线一个线程能够保存多个副本以上,就需要创建多个ThreadLocal。 2 ThreadLocal内部的ThreadLocalMap键为弱引用,会有内存泄漏的风险...

    Java并发编程原理与实战

    了解多线程所带来的安全风险.mp4 从线程的优先级看饥饿问题.mp4 从Java字节码的角度看线程安全性问题.mp4 synchronized保证线程安全的原理(理论层面).mp4 synchronized保证线程安全的原理(jvm层面).mp4 单例问题...

    Java-Interview-Offer

    多线程 线程的创造 线程的生命周期 线程的同步 死锁 新特性 网络编程 网络通信协议 TCP协议与UDP协议 数据库 关系型数据库 MySQL SQL语句 DML,DCL,DDL 事物 索引 非关系型数据库 阶段二:JavaWEB XML格式 WEB...

    龙果 java并发编程原理实战

    第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 ...

    Java 并发编程原理与实战视频

    第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 ...

    龙果java并发编程完整视频

    第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 ...

    java并发编程

    第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 ...

    lectures:CprE 308 的讲义幻灯片

    / 3 文件系统接口 / 多道程序设计 / 主题介绍 / 4 线程实现HTML / PDF 用户和内核线程HTML / PDF 5 互斥HTML / PDF 生产者/消费者HTML / PDF 6 读者/作家HTML / PDF 餐饮哲学家HTML / PDF 7 死锁HTML / PDF 8 僵局/...

    2018年面试实战总结.zip

    2018/09/15 周六 下午 15:47 28,460 Java多线程面试题50.docx 2018/10/03 周三 下午 17:15 22,866 Java用自定义的类作为HashMap的key值 实例详解.docx 2018/09/16 周日 上午 11:02 98,953 Java程序的执行过程.docx ...

Global site tag (gtag.js) - Google Analytics