`

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
分享到:
评论

相关推荐

    spring4+junit4.8 +多线程TheadTool

    TheadTool可能是自定义的工具类,用于简化多线程编程,比如提供线程的启动、停止、同步控制等功能。在Spring4中,我们可以利用`org.springframework.util.concurrent.ListenableFuture`或`java.util.concurrent....

    线程中获取spring 注解bean

    线程中的操作往往涉及到多线程环境下的资源共享和管理,因此,如何在线程中正确地获取并使用Spring通过注解注入的对象,是一个常见的问题。本文将详细探讨这个主题。 首先,Spring的注解主要分为三类:配置注解(如...

    java 后端学习资料包含(spring,多线程).zip

    多线程编程还需要关注死锁、活锁、饥饿等问题,以及如何有效地避免和解决这些问题。 在Spring框架中,多线程的应用主要体现在并发处理和异步任务上。Spring的`ThreadPoolTaskExecutor`和`AsyncConfigurer`接口可以...

    基于Spring+Ibatis的安全线程实现

    4. **线程池管理**:Spring提供ThreadPoolTaskExecutor,我们可以自定义线程池配置,比如核心线程数、最大线程数、队列长度等,以优化多线程执行效率,并通过设置RejectedExecutionHandler处理拒绝策略。 5. **事务...

    多线程及spring相关面试专题及答案.zip

    在IT行业中,多线程和Spring框架是两个非常重要的领域,尤其对于后端开发者来说,它们是必备的技术栈。下面将分别对这两个主题进行详细的知识点解析。 **多线程** 1. **线程概念**:线程是操作系统分配CPU时间片的...

    自己实现的 ActiveMQ 多线程客户端 包含生产消息客户端和消费者消息客户端

    多线程的设计可以提高消息处理的吞吐量,但需要注意线程安全问题,如锁的使用,以避免数据竞争和死锁。 8. **测试和调试**: 对于这样的多线程应用,进行充分的单元测试和集成测试是必要的,以确保在各种场景下都...

    spring boot多线程教学演示系统(源码+数据库)011733

    标题中的"spring boot多线程教学演示系统"表明这是一个基于Spring Boot框架的项目,用于教学和演示多线程技术的应用。Spring Boot是Java生态中一个流行的微服务开发框架,它简化了Spring应用的初始设置和配置,使得...

    多线程精品资源--novel 是一套基于时下最新 Java 技术栈 Spring Boot 3 + Vue 3 开发.zip

    【标题】中的“多线程精品资源--novel”表明这是一个关于多线程编程的高质量学习资料,结合“基于时下最新 Java 技术栈 Spring Boot 3 + Vue 3 开发”,我们可以推断出这是一套综合了后端与前端开发的教程,主要聚焦...

    spring boot《Java课程》多线程教学演示系统(011733)

    在本课程中,"Spring Boot《Java课程》多线程教学演示系统(011733)",我们将深入探讨Java编程语言的核心特性之一——多线程,并结合Spring Boot框架构建一个实际的教学演示系统。这个系统将帮助我们理解如何在现代...

    解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程问题

    在本文中,我们主要探讨了在使用Spring Session以及Redis作为存储方式时,由于消息监听导致创建大量线程的问题及其解决方案。我们将从Spring Session的基础知识、Redis在Spring Session中的作用、监听机制导致线程...

    SpringMVC简介与多线程解决方案

    通过这种方式,SpringMVC与多线程结合,可以优化复杂的Web应用程序,提升并发处理能力,为高并发场景提供更佳的性能表现。在实际项目中,还需要根据业务需求和系统资源进行合理的线程管理和优化。

    WEB多线程开发

    - **死锁和竞态条件**:识别和预防这两种常见的多线程问题,确保程序的稳定性和可靠性。 - **线程通信**:了解`wait()`, `notify()`, `notifyAll()`方法以及`BlockingQueue`等同步机制,用于线程间的通信和协作。 - ...

    多线程并发学习书籍

    在IT行业中,多线程并发编程是至关重要的一个领域,特别是在服务器端开发、大数据处理以及高性能计算中。这里提到的“多线程并发学习书籍”集合包含六本关于这一主题的专业书籍,覆盖了2012年至2018年的最新知识。...

    Java多线程.pdf

    Java多线程是Java编程中不可或缺的一个重要概念,它允许程序在同一时间执行多个任务,从而提高了计算机系统的资源利用率和程序的响应速度。本篇将详细阐述Java多线程的基础知识,包括线程的概念、创建线程的方式以及...

    java多线程_设计模式_各种技术(我的书架)

    然而,多线程也带来了挑战,比如竞态条件、死锁、资源争抢等问题,这些都需要通过同步机制如`synchronized`关键字、Locks(如ReentrantLock)以及volatile变量来解决。另外,Java提供了ThreadLocal来解决线程局部...

    架构师学习线路图,详细介绍java学习线路图,包括java多线程并发,JVM,spring,springboot,s.zip

    理解线程同步机制,如synchronized、wait/notify、ReentrantLock等,以及死锁、活锁、饥饿等问题的预防和处理,都是深入学习多线程并发的重要内容。 2. **JVM(Java虚拟机)**:JVM是Java程序运行的平台,理解其...

    springmvc+spring线程池处理http并发请求数据同步控制问题

    同时,Spring框架提供的线程池功能则可以帮助我们优化多线程环境下的性能,特别是处理并发请求时。在这个主题中,我们将深入探讨如何利用Spring MVC与Spring线程池来有效地管理并发请求,并解决数据同步控制问题。 ...

    多线程学习代码

    本文将围绕"多线程学习代码"这个主题,详细讲解其中涉及的Spring动态代理和Java多线程锁的使用,并探讨与JVM特性相关的知识。 首先,让我们来关注Spring框架中的动态代理。动态代理主要分为两种类型:JDK动态代理和...

    java高级教程分布式多线程中间件-网盘整理合集

    在Java编程领域,分布式多线程中间件是高级主题,涉及到复杂的系统设计和优化。本教程合集将深入探讨这些核心概念,旨在帮助开发者提升技能并应对大型、高并发的应用场景。 首先,让我们来理解“Java高级教程”的...

    java面试宝典,包含java基础篇、多线程、spring、springboot、mysql、redis、mq等等经典面试问题

    这份资源包含了Java基础、多线程、Spring框架、Spring Boot、MySQL数据库、Redis缓存以及消息队列MQ等多个核心知识点,每个部分都涵盖了经典且常见的面试问题。 1. **Java基础篇**: - 内存模型:了解JVM内存结构...

Global site tag (gtag.js) - Google Analytics