java - 在 Java DAO 上使用同步是否会导致问题?

标签 java multithreading web-applications dao synchronized

在 Java DAO 中的方法上使用“synchronized”关键字是否会在 Web 应用程序使用时导致问题?

我问这个问题是因为我有一个多线程独立应用程序,需要同步方法以避免资源冲突,如此处所示。

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection

我担心的是,当大量人尝试使用该应用程序时,同步方法将阻塞并减慢整个应用程序的速度。

我正在使用 Spring 注入(inject)的 JPA 实体管理器工厂,它为 DAO 提供实体管理器。从技术上讲,我可以删除 DAO 层并让类直接调用实体管理器工厂,但我喜欢 DAO 提供的分离。

我还应该注意,我非常小心,不要在线程之间传递连接的实体 ORM 对象。我推测是访问DAO时出现资源冲突错误。我认为多个线程同时进行,并尝试以非原子方式持久保存或从数据库中读取。

在这种情况下,使用 DAO 是否弊大于利?


我在问题中遗漏的一大信息是 DAO 不是单例。如果我的思考足够清晰,能够包含这些细节,我可能一开始就不会问这个问题。

如果我理解正确的话,Spring 会为每个使用 DAO 类的类创建一个新实例。因此,每个线程的支持实体管理器应该是唯一的。正如 Rob H 回答的那样,不共享实体管理器是这里的关键。

但是,现在我不明白为什么在删除同步时会出现错误。


根据这个thread ,@PersistenceContext注释创建一个线程安全的SharedEntityManager。所以您应该能够创建一个单例 DAO。

最佳答案

您说您没有跨线程共享实体对象。那挺好的。但您还应该确保您没有跨线程共享 EntityManager 对象(或 Hibernate 中的 Session 对象)。像 Spring 这样的框架通过将 session 存储在线程局部变量中来自动为您管理此操作。如果您在没有框架帮助的情况下编写自己的 DAO,则需要自己采取预防措施以避免共享它们。

一旦执行此操作,就没有理由同步 DAO 方法,因为任何 session 状态都不会跨线程共享。这对于高度并发的 Web 应用程序至关重要。另一种方法是,假设它们都共享同一个 DAO 实例,则一次只有一个线程能够访问 DAO。对于吞吐量来说一点也不好。

关于java - 在 Java DAO 上使用同步是否会导致问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1110328/

相关文章:

java - 以编程方式获取 Tomcat 的 "appBase"目录?

java - JBoss AS 7.1.1 中的跨域 POST

java - 如何从 maven-archetype-webapp 工件生成 Ear 文件?

java - 使用 RC4 在 java 中加密字符串并在 VBScript 中解密

java - 这两种将集合转换为数组对象的方法的区别

java - 如何根据对象的单个属性匹配删除列表中的重复对象?

multithreading - Kafka流中通过线程分配的策略是什么?

python - 线程不允许在 python Flask 中保存文件

java - 为什么在 Java 中停止一个线程这么难?

caching - Web 应用程序的缓存中应该存储什么?