【发布时间】:2011-09-22 16:25:51
【问题描述】:
在一次关于 Spring/Hibernate 事务的演讲中,我提出了一个观点,即方法上的 synchronized 关键字和 @Transactional 在逻辑上具有许多相似之处。果然,它们是完全不同的野兽,但它们都作为方法的方面应用,并且都通过某种共享监视器(例如,记录在 db 中)控制对某些资源的访问。
人群中有几个人立即反对并声称我的比较是致命的错误。我不记得具体的论点,但我也可以在这里看到一些观点。例如,synchronized 从一开始就适用于整个方法,事务只有在到达访问数据库的语句时才会生效。另外synchronized 不提供任何读/写锁定模式。
所以问题是,我的比较完全错误,我永远不应该使用它,或者,用适当的措辞,将它展示给熟悉synchronized 工作原理但仍在努力学习的经验丰富的工程师是否有意义关于 AOP 事务?这个措辞应该是什么?
一点更新。
显然我的问题听起来像是比较 DB 事务与在 Java 中输入 synchronized 方法。事实并非如此。我的想法更多是比较@Transactional 和synchronized 语义上的相似性。
我提出它的一个原因也是为了说明传播行为。例如,如果@Transactional 是 PROPAGATION_REQUIRED,那么它与进入synchronized 块有很多相似之处。对于交易:如果存在交易,我们就继续使用它,如果不存在,我们将创建一个。对于synchronized,如果我们已经有监视器,我们继续处理它,如果没有,我们将尝试获取它。当然对于@Transactional,我们不会锁定方法边界。
【问题讨论】:
-
它们是完全不同的野兽,我认为继续使用这种比较只会给你的观众带来混乱。
-
只是指出非常明显的一点:事务可以提交和回滚,同步确保只有独占访问。没有任何共同点,因为甚至不需要事务来锁定对象。
-
请注意,我不是在比较 DB 事务与 JVM 监视器操作,而只是在
synchronized和@Transactional语义上的相似之处 -
对于同步,如果我们已经有监视器,我们继续它,如果没有,我们将尝试获取它。实际上它确实增加了获取的计数,因此您应该考虑它Int,没有类似于传播类型的布尔值。在这种情况下,当计数达到零时释放锁,这与由容器定义的提交或回滚的事务传播不同。旁注是,您应该避免同步。在整个方法 b/c 上,大多数时候不应该锁定整个代码路径。
标签: java multithreading hibernate spring transactions