说明
阅读dubbo官方文档,看到初始化死锁部分,特地在此记录一番,并结合线上业务给出可能的解决方案。
死锁产生的原因
当spring解析到<dubbo:serivce />时,就已经向外暴露了服务,而spring还在初始化其他的bean,此时如果有消费者的请求进来,并且服务的提供者类中含有调用applicationContext.getBean()的用法时,那么会产生死锁。
请求线程的applicationContext.getBean()方法,会先同步singletonObjects判断bean是否存在,不存在则同步beanDefinitionMap进行初始化,并再次同步singletonObjects写入该bean;
而对于spring初始化线程来说,是不需要判断bean是否存在的,直接同步beanDefinitionMap进行初始化,并同步singletonObjects写入该bean;
此时就发生了死锁:请求线程先锁singletonObjects,再锁beanDefinitionMap,最后再锁singleObjects;而spring初始化线程先锁beanDefinitionMap,再锁singleObjects,反向锁导致线程死锁(即当需要加多把锁,但是加锁的顺序不一致时,会产生死锁),此时启动失败,无法提供服务。
(扩展:springIOC容器中有两个重要的map–beanDefinitionMap和singletonObjects&#x