【Spring】IOC容器并发条件上,可能发生死锁
【Spring】IOC容器并发条件下,可能发生死锁1.背景 ?代码十分简单,如下:?package com.alibaba.testimport or
【Spring】IOC容器并发条件下,可能发生死锁
1.背景
?
代码十分简单,如下:
?
package com.alibaba.test;import org.springframework.context.support.ClassPathXmlApplicationContext;public class DeadLockTest { ClassPathXmlApplicationContext context = null; public void startContext() { context = new ClassPathXmlApplicationContext(); context.setConfigLocation("spring/bean/mybeans.xml"); context.refresh(); } public void getBean() { new Thread(new GetBean()).start(); } /** * @param args */ public static void main(String[] args) { DeadLockTest t = new DeadLockTest(); //get bean 工作线程 t.getBean(); //容器启动主线程 t.startContext(); } //get bean 工作线程 class GetBean implements Runnable { public void run() { try { Thread.sleep(10000); MyBean myBean = (MyBean) context.getBean("myBean"); myBean.getOtherBean().sayHello(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // TODO Auto-generated method stub } }}?
其中mybean定义如下(一定要用注解的注入方式,才会有可能发生死锁!):
?
?package com.alibaba.test;import org.springframework.beans.factory.annotation.Autowired;public class MyBean { @Autowired private OtherBean otherBean; public OtherBean getOtherBean() { return otherBean; } public void setOtherBean(OtherBean otherBean) { this.otherBean = otherBean; } public void sayHello() { otherBean.sayHello(); }}?
myBean.xml:
?<?xml version="1.0" encoding="GB2312"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans default-autowire="byName"><bean/><bean id="myBean" /></beans>?
以上代码经过调试控制,即会发生思索,控制如下:
1.main线程在DefaultListableBeanFactory.preInstantiateSingletons 方法的
synchronized (this.beanDefinitionMap) {
...
}里加个断点
2.getBean工作线程在DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory singletonFactory)方法的
synchronized (this.singletonObjects) {
...
}里加个断点。
3.等1,2断点都进去之后,再触发继续运行,就会发生死锁。
?
结论也许可以算是 spring 的 bug ,也许可以算我们使用不当。
?
总之,有两点需要注意:
1.?????? 尽量避免显式调用 ioc 容器,注入工作由容器自己来完成。
2.?????? 尽量在容器初始化完,开始对外服务。