This post is about my exploration with JRuby and Clojure more in terms of how to use the Clojure's STM infrastructure. Whenever I find an interesting Java library the first thing I do is to import it into JRuby and play with it for sometime. After working with Clojure I wanted to use its STM in Ruby and finally found time to do it. The code is really crude as it explores very basic functionality of STM. May be as I keep working I will try to build something around this and who knows it can end up as a library for JRuby :)...
Instead of defining STMs myself - Here it is from Wikipedia..
"In computer science, software transactional memory (STM) is a concurrency control mechanism analogous to database transactions for controlling access to shared memory in concurrent computing. It functions as an alternative to lock-based synchronization. A transaction in this context is a piece of code that executes a series of reads and writes to shared memory. These reads and writes logically occur at a single instant in time; intermediate states are not visible to other (successful) transactions."
As most of you know the problem is with sharing the state.. In this example my_account balance. Imagine when two different threads of execution trying to update the value at the same time. Disastrous results may ensue. So the typical approach is locking of the shared resource. Problem with locking is it effectively limits concurrency as well is too hard to get it right. So we have started looking for other models of concurrency. Actors, Dataflow and STMs are some of the popular form. As you see in the example let's say there is a shared resource. If we need to update it we can't update it in a separate context. We need to run this as a part of transaction and as database transactions it is all or nothing.
In Clojure's term a ref can be updated only inside the context of a transaction. Else it will throw IllegalStateException. As well the ref getting updated will not be visible to outside work till the end of the transaction. The transactions are composable which is difficult in cases of threads and locks. Also as the example shows STM is a form of optimistic concurrency. Everyone can update the shared resource but whoever finishes first and commits wins. Others fail because the state now is different from what they started with and they can try.
The code is almost self explanatory and simple. Using clojure STM is pretty simple and straightforward. And this will help us to effectively manage concurrent access of shared resource by multiple threads.
Let me know your thoughts...