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...



4 comments:
Nice post, Sai. Also shows how we can use the best tool for a job, thanks to the JVM. The only thing that leaves me a bit concerned is how we mix Ruby and Clojure - gotta use JRuby, so not portable for all Ruby apps. Is it time to 'declare' JRuby as a super-set language of Ruby and move ahead? Or keep it shackled down to Ruby-compliance-requirements?
It's tricky, and that's where I think Scala + Clojure may be a good mix. Throw away the Java language, and move on with the JVM.
JVM is best as a platform. I have already moved away from using or advocating java as a language. Clojure, Scala and JRuby seem to do a really good job in that.
The one advantage with Java over Ruby is the wealth of infrastructure already available in Java and the amount of work it takes to replicate that :). JRuby runs RubySpec so it will be compatible with other Ruby VMs.
Sure, I was never doubting the compatibility goals of JRuby to the Ruby motherland. I was only wondering if JRuby is being held back due to that.
But thanks to the JVM, atleast I know I can play with and mix many other tools I have on the JVM. We'll need to evolve practical ways around mixing various JVM languages, get general acceptance around them, and start using them in a much more larger and concerted way. :)
I understand the concern. But I don't think JRuby is going to evolve beyond Ruby. It is gonna be a mirror image of MRI with JVM as platform and not as a separate entity itself. That's why I think there is no support for annotations till now as, Ruby as a language doesn't have support for it.
Post a Comment