Handling concurrency using optimistic locking technique
In a real world scenario, we deal with concurrency mostly during a
database update .To be more specific, if a specific row in database table
is being processed by two concurrent threads/process one should not
update the stale data. Personally, I never liked the concepts of
synchronized, Lock, Wait, etc to achieve the above results. As a developer
we all use some sort of Version control system (CVS stands for Concurrent
version control). Its kind of pretty well known fact that versioning is
the one of the best way to avoid concurrency(much better compared to
even timestamps).
Most of the modern persistence frameworks like Hibernate, Ibatis, JPA, etc suppport automatic versioning at row level. A hibernate sample will look like,
< class name="foo" optimistic-lock="version" table="FOOS">
....
< version column="version" name="version" type="int">
....
< /class>
When there is a update operation on the FOOS table,
(1) Hibernate issues an update statement like
UPDATE FOOS SET BAR='bar', VERSION=2
WHERE ID=1234 AND VERSION=1
(2) Hibernate checks the JDBC row count, and throws a StaleObjectStateException if no rows were updated
You don't have to worry much about other things. Most of the current persistence framework will automatically update/check the version number during each update.
And moreover, the classic Synchronized,Lock,Wait,etc approach is tied to that specific JVM.If you are running a distributed application across different JVM's,you have more things to worry about..
Published at DZone with permission of Ramsundar Kuppusamy, author and DZone MVB. (source)Most of the modern persistence frameworks like Hibernate, Ibatis, JPA, etc suppport automatic versioning at row level. A hibernate sample will look like,
< class name="foo" optimistic-lock="version" table="FOOS">
....
< version column="version" name="version" type="int">
....
< /class>
When there is a update operation on the FOOS table,
(1) Hibernate issues an update statement like
UPDATE FOOS SET BAR='bar', VERSION=2
WHERE ID=1234 AND VERSION=1
(2) Hibernate checks the JDBC row count, and throws a StaleObjectStateException if no rows were updated
You don't have to worry much about other things. Most of the current persistence framework will automatically update/check the version number during each update.
And moreover, the classic Synchronized,Lock,Wait,etc approach is tied to that specific JVM.If you are running a distributed application across different JVM's,you have more things to worry about..
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)
Tags:






Comments
Nick Wiedenbrueck replied on Wed, 2010/05/26 - 9:13am
Steven Devijver replied on Wed, 2010/05/26 - 9:52am
How do I avoid instance variables when using Hibernate? Doesn't compute ...
Jordan Zimmerman replied on Wed, 2010/05/26 - 12:38pm
"In a real world scenario, we deal with concurrency mostly during a database update"
This is an odd statement. Did you meant to say "transactions"? concurrency != transactions. Concurrency issues arise due to shard state. Given Java's memory model and non-deterministic issues regarding threading, it's extremely difficult to understand how to correctly use shared state.
Quick - without Googling - explain why the double-checked lock pattern doesn't work (can you name every single problem with it?).
Scott Hickey replied on Wed, 2010/05/26 - 4:51pm
Yes it is hard, and your article displays a fundemental lack of experience with concurrency.
Between this article and the one on Java Reflection last week, I think the editorial standards might a little weak lately. Not trying to start a flame war - but the difficulty of Java concurrency is pretty uncontraversial.
I encourage you to write an article about comparing/contrasting immutablilty in Scala, Clojure or Groovy and how it relates to what's required in Java - it would be more enlightening.
Muthu Jayakumar replied on Wed, 2010/05/26 - 2:14pm
Jordan Zimmerman replied on Wed, 2010/05/26 - 3:17pm
"With Java 5 Concurrency API, I believe that handling multi-threaded model has been simplified"
Simplified, yes; but not made easy.
Stefan Zobel replied on Wed, 2010/05/26 - 4:07pm
Rogerio Liesenfeld replied on Wed, 2010/05/26 - 4:54pm
Actually, "double-checked" locking *does* work. (Well, in Java 5+ anyway.)
Jordan Zimmerman replied on Wed, 2010/05/26 - 4:56pm
in response to:
Rogerio Liesenfeld
>Actually, "double-checked" locking *does* work. (Well, in Java 5+ anyway.)
It depends how you write it. You must make the lock instance volatile. The point is that writing it correctly requires a non-obvious recipe. If you miss even one step your code will not be safe but will still compile and will work some of the time.
Jordan Zimmerman replied on Wed, 2010/05/26 - 5:01pm
Actually, I was just doing some research, and double-checked locking may still be broken in Java 5. I need to check this, but the Java 5 memory model still allows out of order execution outside of synchronized blocks. The thing that I'm not sure about is if volatile turns that off.
But, this just proves the point. In order to get these things correct you must have highly specialized knowledge that you will encounter conflicting opinions about.
Jason Marshall replied on Wed, 2010/05/26 - 5:03pm
Not exactly. Your broken DCL code from 1.4 is still broken.
What changed is that prior to 1.5 there was no code you could write that would make it work. Now, you can modifiy the DCL pattern so it will work.
That said, it's still a bad idea. It's a code smell for not having your application initialization lifecycle under control.
Rogerio Liesenfeld replied on Wed, 2010/05/26 - 5:19pm
in response to:
Jason Marshall
But I agree that, whenever possible, it's best to avoid using this idiom/pattern.
Russel Winder replied on Thu, 2010/05/27 - 8:14am
Russel Winder replied on Thu, 2010/05/27 - 8:16am
in response to:
Scott Hickey
Ramsundar Kuppusamy replied on Thu, 2010/05/27 - 9:00am
@Russel Winder - the intent of article is not to question the benefits of java's concurrent package or threading.They definitely have their own needs and use cases, but in general they add a lot of complexity as @Jordan Zimmerman said,
And more importantly, concurrent package/java threading need not be the default solution for concurrency.using versioning,messaging concept,etc could make things simpler and easily maintainable.
Endre Varga replied on Thu, 2010/05/27 - 9:22am
I have not much to say about this article, but I have to say that I am really infuriated with all the concurenncy "Silver Bullets" spilled on our heads.
I do discrete event simulations for a living which is almost like programming Actors. Same message passing, same asynchronous nature -- the only difference is the strict time ordering requirement in simulations. We invented blocking calls for a reason. They are much easier to understand than convoluted custom state tracking needed by any more than trivial protocol between Actors. STM has its own problems. There are many cases when Actors are simply worse than threads. Stop this FUD about threads and traditional concurrency tools. They have their drawbacks JUST AS THE OTHERS HAVE THEIR OWN.
Jason Marshall replied on Thu, 2010/05/27 - 12:22pm
in response to:
Endre Varga
I think a lot of people who fight these "Which concurrency idiom is the One True Idiom" forget that most of the ones they argue about were popularized (and named) by the same person - The Late Great C.R. Hoare.
Gavin White replied on Mon, 2010/05/31 - 6:04am
Tanya Huff replied on Thu, 2011/05/05 - 10:58pm
in response to:
Nick Wiedenbrueck