Java synchronized关键字和Spring @Transactional注释的逻辑比较

时间:2011-06-25 17:08:45

标签: java multithreading hibernate spring transactions

在关于Spring / Hibernate交易的一篇演讲中,我提出了一个观点,即方法上的synchronized关键字和@Transactional在逻辑上有许多相似之处。果然它们是完全不同的野兽,但它们都作为方法应用于方法,并且通过某种共享监视器控制对某些资源的访问(例如,在db中记录)。

人群中有几个人立即反对并声称我的比较是错误的。我不记得具体的论点,但我也可以在这里看到一些观点。例如,synchronized从一开始就适用于整个方法,只有达到访问DB的语句时,事务才会生效。 Plus synchronized不提供任何读/写锁定模式。

所以问题是,我的比较是完全错误的,我永远不应该使用它,或者,如果使用正确的措辞,将它呈现给那些熟悉synchronized工作但仍在尝试的经验丰富的工程师是否有意义了解AOP交易?这个措辞应该是什么?


稍微更新。

显然我的问题听起来像比较数据库事务与在Java中输入synchronized方法。事实并非如此。我的想法更多的是比较@Transactionalsynchronized的语义相似性。

我提出它的原因之一也是为了说明传播行为。例如,如果@Transactional是PROPAGATION_REQUIRED,则它与输入synchronized块有许多相似之处。对于交易:如果交易存在,我们只是继续使用它,如果没有,我们将创建一个。对于synchronized,如果我们已经有监视器,我们继续进行监视,如果没有,我们将尝试获取它。当然对@Transactional我们不会锁定方法边界。

2 个答案:

答案 0 :(得分:4)

如果我们将@Transactional视为表示锁定数据库资源的方法(因为它在事务中使用) - 那么这种比较是有道理的。

然而,这就是他们的共同点。 synchronized是在对象监视器上定义的(并且仅保护它),这在使用关键字时是已知的,而事务可以锁定多个资源(在事务开始时不知道),或者可能不锁定任何资源根本(乐观锁定,只读事务)。

所以最终 - 不要使用那种比较,它们有很多不同之处,而不是共同点。

答案 1 :(得分:3)

@Transactional注释中体现的概念比synchronized关键字中体现的概念要复杂得多。我同意JB Nizet的评论,即你的比较是违反直觉的,会让你的观众感到困惑。

通过Java同步,您始终可以确切地知道锁定的内容,从代码中的哪一点到哪一点。您已经内置了线程的概念和竞争相同资源的线程队列。此外,您实际上是锁定代码,而不是锁定数据。这似乎是一种细微差别,但差异可能很大。

使用@Transactional,首先要解决事务划分问题。您不确切知道事务何时开始,因为您可能在已经打开事务后达到此方法。出于同样的原因,您不知道退出方法时交易是否会结束。

其次,事务隔离语义比仅仅同步(只读,读写等)复杂得多。很多时候,隔离会回答关于数据完整性的问题,而不是本质上关于排队访问资源的问题。有时只有一个记录被锁定,有时是整个表(再次,这是数据,而不是代码)。此外,事务可以回滚,这个概念对于数据完整性很重要,而synchronized则不存在。