简体   繁体   English

在触发应用程序事件时创建bean时,如何避免Spring中的死锁?

[英]How can i avoid a deadlock in Spring when creating a bean while triggering an application event?

A deadlock occurs in my application while one thread performs a query on a mongo db, causing an application event to be fired, while another thread attempts to create a bean with an AutowireCapableBeanFactory . 我的应用程序发生死锁,而一个线程在mongo db上执行查询,导致应用程序事件被触发,而另一个线程尝试使用AutowireCapableBeanFactory创建一个bean。

This happens in the constructor of a @Service and prevents the startup of the entire application as the service is created on startup. 这发生在@Service的构造函数中,并在启动时创建服务时阻止整个应用程序的启动。

Pseudocode: 伪代码:

@Service
public class MyService {

    @Autowired
    public MyService(AutowireCapableBeanFactory factory, TaskScheduler scheduler) {
        MyFirstCommand command1 = factory.getBean(MyFirstCommand.class);
        scheduler.schedule(command1, new Date());

        MySecondCommand command2 = factory.getBean(MySecondCommand.class);
        scheduler.schedule(command2, new Date());
    }
}

public class MyFirstCommand extends Runnable {

    @Autowired MongoOperations mongo;

    @Override
    public void run() {
       mongo.findById("some-id", MyData.class); 
    }
}

Note that i have some AbstractMongoEventListener s registered as @Component s. 请注意,我有一些AbstractMongoEventListener注册为@Component s。

The deadlock occurs while one thread in MyFirstCommand.run() performs mongo.findById() . MyFirstCommand.run()一个线程执行mongo.findById()时发生死锁。 The other thread is in the constructor of MyService performing factory.getBean(MySecondCommand.class): 另一个线程在MyService的构造函数中执行factory.getBean(MySecondCommand.class):

Found one Java-level deadlock:
=============================
"pool-1-thread-1":
  waiting to lock monitor 0x00007fd05d5bf5d8 (object 0x00000000816d0970, a java.util.concurrent.ConcurrentHashMap),
  which is held by "main"
"main":
  waiting for ownable synchronizer 0x0000000081ed8468, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync),
  which is held by "pool-1-thread-1"


Java stack information for the threads listed above:
===================================================
"pool-1-thread-1":
at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:179)
- waiting to lock <0x00000000816d0970> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:335)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:326)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:179)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:139)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:66)
at org.springframework.data.mongodb.core.MongoTemplate.determineCollectionName(MongoTemplate.java:1976)
at org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:607)


"main":
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x0000000081ed8468> (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireShared(AbstractQueuedSynchronizer.java:967)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1283)
at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock.java:727)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:160)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:139)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:66)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getEntityInformation(MongoRepositoryFactory.java:118)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getTargetRepository(MongoRepositoryFactory.java:92)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:185)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean.afterPropertiesSet(MongoRepositoryFactoryBean.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 

How come Spring isn't thread safe here? 为什么Spring在这里不是线程安全的? What can i do to avoid this deadlock? 我该怎么做才能避免这种僵局?

This deadlock occurs due to a bug in Spring. 由于Spring中的错误导致此死锁。 I have created an issue in their JIRA: DATACMNS-901 . 我在他们的JIRA中创建了一个问题: DATACMNS-901

As a workaround i am now creating all runnable beans before scheduling them: 作为一种解决方法,我现在在安排所有可运行的bean之前创建它们:

@Autowired
public MyService(AutowireCapableBeanFactory factory, TaskScheduler scheduler) {
    MyFirstCommand command1 = factory.getBean(MyFirstCommand.class);
    MySecondCommand command2 = factory.getBean(MySecondCommand.class);

    scheduler.schedule(command2, new Date());
    scheduler.schedule(command1, new Date());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 运行 Spring Boot 应用程序时创建 bean 时出错 - Error creating bean when I run spring boot application 创建Spring应用程序时Bean创建异常 - Bean Creation Exception when creating spring application 在 DefaultSingletonBeanRegistry 和 CachingConnectionFactory 中创建 bean 时出现死锁 - Deadlock while creating bean in DefaultSingletonBeanRegistry and CachingConnectionFactory 如何禁用在 Spring 中使用 @Component 注释创建 bean? - How can I disable creating bean with @Component annotation in Spring? 我在使用 Spring 创建电报机器人时遇到 bean 问题 - I have problems with bean while creating telegram bot using Spring 在 spring 中使用 applicationContext.getBean() 创建 bean 时如何指定要使用的组件? - How do I specify which component to use while creating the bean using applicationContext.getBean() in spring? 如何在同时保存数据的同时避免spring数据neo4j ogm中的死锁 - how to avoid deadlock in spring data neo4j ogm while saving data concurrently 从单个 CompletableFuture 创建多个相互依赖的期货时如何避免死锁? - How to avoid deadlock when creating multiple interdependent futures from a single CompletableFuture? 使用Spring,如何将子bean注入父bean? - With Spring, how can I inject a child bean in a parent bean? 使用 Spring Boot 2.2+,当应用程序不在云平台上运行时,如何创建 bean - With Spring Boot 2.2+, how can you create a bean when the application is NOT running on a Cloud Platform
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM