开发者

Logical comparison of Java synchronized keyword and Spring @Transactional annotation

At one of presentations about Spring/Hibernate transactions I brought up an opinion that synchronized keyword on a method and @Transactional logically have many similarities. Sure enough they are totally different beasts but yet they both applied as aspects to the method and both control access to some resources via some kind of shared monitor (record in db, for example).

There were couple of people in the crowd who i开发者_JAVA百科mmediately opposed and claimed that my comparison is fatally wrong. I don't remember specific arguments but I can see some point here as well. For example, synchronized works for the entire method from the beginning and transaction will only have effect when statement to access DB is reached. Plus synchronized does not offer any read/write locking pattern.

So the question is, is my comparison totally wrong and I should never ever use it, or, with proper wording, would it make sense to present it to experienced engineers who know well how synchronized works but yet trying to learn about AOP transactions? What this wording should be?


A bit of update.

Apparently my question sounded like comparing DB transactions vs entering synchronized method in Java. That's not the case. My idea is more about comparing similarities in semantics of @Transactional and synchronized.

One of the reason I brought it up also was to illustrate propagation behavior. For example, if @Transactional is PROPAGATION_REQUIRED it will have many similarities to entering synchronized block. For transaction: if transaction is present we just continue using it and if not, we will create one. For synchronized, if we already have monitor we proceed with it and if not we will attempt to acquire it. Of course for @Transactional we are not going to lock on method boundary.


If we look at @Transactional as denoting a method that locks a database resource (because it is used in the transaction) - then the comparison makes some sense.

However this is all they have in common. synchronized is defined on an object monitor (and protects only it), which is known at the time of usage of the keyword, while a transaction may lock multiple resources (that are not known when the transaction starts), or may not lock any resources at all (optimistic locking, read-only transactions).

So ultimately - don't use that comparison, there are a lot more things that they differ in than they have in common.


The concepts embodied in @Transactional annotation are much more complex than those embodied in synchronized keyword. I agree with JB Nizet's comment that your comparison is counter-intuitive and would confuse your audience.

With Java synchronization, you always know exactly what is being locked, from which point in the code and to which point. You have built-in the concept of threads and a queue of threads competing for the same resource. Also, you are in effect locking code, not locking data. It may seem like a nuance, but the difference could be substantial.

With @Transactional, first you have the issue of transactions demarcation. You don't know exactly when a transaction begins, since you might reach this method after already having opened a transaction. For the same reason, you don't know if the transaction will end when you exit the method.

Secondly, transaction isolation semantics are much more complex then just synchronization (read-only, read-write, etc.). Many times isolation answers a concern about data integrity, and not intrinsically a concern about queuing access to a resource. Sometimes just one record is locked, sometimes a whole table (again, this is data, not code). Further more, transactions can be rolled-back, a concept that is important for data integrity and doesn't exist with synchronized.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜