Spring的TransactionTemplate和SimpleJdbcTemplate是线程安全的吗?

时间:2011-07-19 12:54:42

标签: java spring thread-safety

我目前正在处理代码,其中有一个单例,它被许多线程使用,并且没有状态,除了用于在单例函数中访问数据库的TransactionTemplate和SimpleJdbcTemplate的两个字段。

这是安全还是我应该在需要时创建一个新模板?

4 个答案:

答案 0 :(得分:16)

SimpleJdbcTemplate只包装了一个JdbcTemplate,it's thread-safe就像the TransactionTemplate一样。

答案 1 :(得分:2)

Actualy 。请参阅源代码以获取证明。至少TransactionTemplate的非最终成员 transactionManager 对于已创建的主题可能不可见。此外,它从DefaultTransactionDefinition派生所有非final和publicaly可变成员。

实际上,在加载时,动态容器(如OSGI)可以在TransactionTemplate内使用事务管理器时获得NPE。特别是如果您自己创建TransactionTemplate(而不是通过Spring上下文)。这是因为工作线程(例如Web请求处理器)已经创建并且是热的(具有自己的线程绑定CPU缓存)。在init线程中创建新的TransactionTemplate时,没有执行内存屏障来刷新线程绑定(或CPU核心绑定)缓存。在极少数情况下,新创建的TransactionTemplate的成员可能对“旧版”不可见。线程。

在热更新正在运行的Web服务之后,我们受到模拟(不完全是使用TransactionTemplate但是使用RetryTemplate)的错误。需要说的是,在Spring Context创建实例的情况下我们没有看到这样的错误,可能是因为在上下文初始化时执行了全局同步。

几乎所有Spring模板类都是可变的,并且内部没有明确的同步。为什么文档说它是线程保存我不明白。

你可以通过在自己的类中创建最终字段来保护自己,因为JMM中的那个语句包含对* Template的引用(参见附件链接):"此外,任何其他对象或数组的可见值这些最终字段引用的内容至少与最终字段一样最新。"

在这种情况下,如果你没有改变* Template实例的状态,它就是"线程安全"。不是通过类设计本身,而是通过特定用法和JMM属性。

请参阅that questionjava memory model on final

答案 2 :(得分:0)

TransactionalTemplate是线程安全的。

最后,TransactionTemplate类的实例是线程安全的,因为该实例不保持任何对话状态。但是,TransactionTemplate实例确实会维护配置状态。因此,尽管许多类可以共享一个TransactionTemplate实例,但是如果一个类需要使用具有不同设置(例如,不同的隔离级别)的TransactionTemplate,则需要创建两个不同的TransactionTemplate实例。

请参见https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/data-access.html#tx-prog-template-settings

SimpleJdbcTemplate已弃用。 参见https://docs.spring.io/autorepo/docs/spring/4.1.3.RELEASE/javadoc-api/index.html?org/springframework/jdbc/core/simple/SimpleJdbcTemplate.html

答案 3 :(得分:0)

单独的线程可以更改事务模板的各种属性(propagationBehaviour、timeout、isolationLevel 等)——当以这种方式使用时,它不是线程安全的。

基本行为(execute、executeWithResult)是线程安全的。