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 immediately 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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With