多线程下Hibernate出现死循环

本文详细分析了在多线程环境下,由于Hibernate session未正确隔离导致的并发问题,特别是当实体对象包含懒加载属性时,如何在不同线程中引发的错误行为。通过深入探讨堆栈信息,我们揭示了问题根源在于多个线程共享同一session,进而导致了死循环现象的发生。解决方案包括合理配置session的生命周期以及避免共享session实例于多线程环境,以确保应用程序的稳定性和性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashMap在多线程下导致死循环的原因可以参考http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html

在多线程环境下,各个线程的Hibernate Session不同,使用Hibernate查询一个实体时,非常罕见的出现了一次,堆栈如下

"pool-130-thread-6" prio=10 tid=0x00002aab010ed800 nid=0x3aba runnable [0x000000004addf000]
   java.lang.Thread.State: RUNNABLE
        at java.util.HashMap.put(HashMap.java:391)
        at org.hibernate.engine.StatefulPersistenceContext.addCollection(StatefulPersistenceContext.java:764)
        at org.hibernate.engine.StatefulPersistenceContext.addUninitializedCollection(StatefulPersistenceContext.java:733)
        at org.hibernate.type.CollectionType.getCollection(CollectionType.java:609)
        at org.hibernate.type.CollectionType.resolveKey(CollectionType.java:408)
        at org.hibernate.type.CollectionType.resolve(CollectionType.java:402)
        at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:120)
        at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:854)
        at org.hibernate.loader.Loader.doQuery(Loader.java:729)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
        at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3049)
        at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:399)
        at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
        at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
        at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:98)
        at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
        at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:836)
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:66)
        at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
        at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150

   

 跟踪调试,发现在多个线程中确实存在相同的session,这些session存在于持久化实体中的CGLIB代理里面

由于这些实体对象是在进入多线程环境之前就已经查询出来了,但是他们关联的对象都是lazy-load,所以都以CGLIB的形式存在与这些实体对象中。于是,在多线程环境下,尽管重新生成了新的session,但是通过实体延迟加载时就会使用之前的session,这样就导致了一个错误的用法:并发使用Hibernate的session

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值