views:

1738

answers:

4

I've got a highly multithreaded app written in Ruby that shares a few instance variables. Writes to these variables are rare (1%) while reads are very common (99%). What is the best way (either in your opinion or in the idiomatic Ruby fashion) to ensure that these threads always see the most up-to-date values involved? Here's some ideas so far that I had (although I'd like your input before I overhaul this):

  • Have a lock that most be used before reading or writing any of these variables (from Java Concurrency in Practice). The downside of this is that it puts a lot of synchronize blocks in my code and I don't see an easy way to avoid it.
  • Use Ruby's freeze method (see here), although it looks equally cumbersome and doesn't give me any of the synchronization benefits that the first option gives.

These options both seem pretty similar but hopefully anyone out there will have a better idea (or can argue well for one of these ideas). I'd also be fine with making the objects immutable so they aren't corrupted or altered in the middle of an operation, but I don't know Ruby well enough to make the call on my own and this question seems to argue that objects are highly mutable.

A: 

The readers-writer lock is a common problem with a well defined solution:

Readers-writer lock

and there are many implementations of it:

Write lock pattern

You do not want to put a lock on for each read/write

billybob
Yes, I've seen these locking facilities before but I can't find a way that Ruby implements them. Ruby has standard locks and monitors but no way I can find to implement a lock that only holds on writes (or other variants).
Chris Bunch
A: 

You have to use a Mutex to synchronize access to the shared state. There really is no way to avoid doing this.

On modern multi-core machines you cannot make any assumptions about how memory will be accessed or how memory accesses will interact with caching.

ewalshe
Yea, that's what I was afraid of doing. I was hoping to find a write lock pattern like billybob described, but I can't find one for Ruby.
Chris Bunch
+4  A: 

Using the lock is the most appropiate way to do this. You can see this presentation by Jim Weirich on the subject: What All Rubyist Should Know About Threading.

Also, freezing an object won't help you here since you want to modify these variables. Freezing them in place means that no further modifications will be applicable to these (and therefore your 1% of writes won't work).

Federico Builes
I got to see this talk in person and it was wonderful. I definitely recommend watching it.
mwilliams
A: 

I haven't used it myself, but you may want to check out Dataflow. It makes all variables write-once.

Andrew Grimm