Preface
Recently, I encountered a deadlock problem when starting the spring project. When using jstack to obtain the thread stack, you can see that two threads have deadlocks:
Solution process:
The source code of DefaultSingletonBeanRegistry.getSingleton() is as follows. You can see that this method requires the singletonObjects to be locked.
The source code of the second xxx.subject.core.cache.DataLocalcacheInit.afterPropertiesSet is as follows:
You can see that when this bean is initialized, it will start the thread and call initData() method of another bean to load data from the database. The initialization of the DataLocalcacheInit bean will be considered complete after the data is loaded.
From the above stack, we can see that when the spring container initializes the bean, it will lock the singletonObjects object; we open a thread in afterPropertiesSet() method, which will eventually trigger spring to load another bean. The first thread (the main thread that initializes spring) has not released the lock, and the second thread (the thread that is opened by itself) also needs to obtain the singletonObjects object lock, which causes a deadlock. The phenomenon shown is that the spring container is stuck there and cannot complete the initialization of all beans.
Let’s take a look at an example, which is very similar to the actual code in our project. FirstBean calls the method in 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...."); }} The ConfigHelper code is as follows: Get another bean through BeanFactory
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(); }} The SecondBean code is simple as follows:
public class SecondBean { public void say() { System.out.println("SecondBean..."); }}The spring configuration file and startup code are as follows. You can find deadlocks when running:
<?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"></bean> <bean id="first"></bean> <bean id="second"></bean> </beans>public class Main { public static void main(String[] args) { ApplicationContext context = new FileSystemXmlApplicationContext( "src/main/java/net/aty/spring/deadlock/deadlock.xml");// Load spring configuration file}}When spring is initialized, if we start the thread to acquire the bean at some extension points provided by spring (BeanFactoryAware/InitializingBean, etc.), the container will be deadlocked. Because spring initializes singleton beans (most beans are singletons) will add locks. If the lock has not been released when 1 bean is initialized, and another thread triggers the spring loading bean again, a deadlock will appear.
Solving the above problem is simple: FirstBean logically depends on ConfigHelper and SecondBean, but we do not show the logical relationship of spring. When spring initializes FirstBean, enter afterPropertiesSet() . This method will trigger the loading of the other 2 beans when the thread is turned on. We just need to show the dependency of spring and let spring load ConfigHelper and SecondBean first.
<bean id="config" depends-on="second"></bean><bean id="first" depends-on="config"></bean><bean id="second"></bean>
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support to Wulin.com.