# DRb and Thread safety

**URL:** <https://rubytalk.org/t/drb-and-thread-safety/37989>\
**Category:** ruby-talk\
**Created:** [31 May 2007 02:29 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989 "2007-05-31T02:29:46Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Erwin\_Abbott](https://avatars.discourse-cdn.com/v4/letter/e/4af34b/32.png) [@Erwin\_Abbott](https://rubytalk.org/u/Erwin_Abbott)\
**Post date:** [31 May 2007 02:29 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/1 "2007-05-31T02:29:46Z")

</div>

I've been reading about DRb and one issue that I still have questions  
about is thread safety. Every website I've come across uses very  
basic examples where the client never does anything that would modify  
the distributed object.

For sake of discussion, let's say I'm writing an application that's  
some kind of database. Clients can add, delete, search, or modify  
records. How can this be written so clients can't step on each other,  
or block the whole database while perfoming and update on a single  
record? Having a mutex for every record doesn't seem very elegant.

I'm also still getting aquainted with threads, and I want to be sure I  
have this right: each thread has it's own "local" variables, so if two  
threads have access to the same array and they both call array.max...  
any local vars used in the #max method won't be "stepped on" by the  
other thread. As long as #max doesn't change any variables outside its  
method scope, it will be thread safe?

Thanks,  
&nbsp;&nbsp;Erwin

---

<div class="post-metadata">

**Author:** ![Eric\_Hodel1](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@Eric\_Hodel1](https://rubytalk.org/u/Eric_Hodel1)\
**Post date:** [31 May 2007 03:45 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/2 "2007-05-31T03:45:02Z")

</div>

> I've been reading about DRb and one issue that I still have questions  
> about is thread safety. Every website I've come across uses very  
> basic examples where the client never does anything that would modify  
> the distributed object.
> 
> For sake of discussion, let's say I'm writing an application that's  
> some kind of database. Clients can add, delete, search, or modify  
> records. How can this be written so clients can't step on each other,  
> or block the whole database while perfoming and update on a single  
> record? Having a mutex for every record doesn't seem very elegant.

Having your database be a Rinda::TupleSpace is one way around it.

> I'm also still getting aquainted with threads, and I want to be sure I  
> have this right: each thread has it's own "local" variables, so if two  
> threads have access to the same array and they both call array.max...  
> any local vars used in the #max method won't be "stepped on" by the  
> other thread. As long as #max doesn't change any variables outside its  
> method scope, it will be thread safe?

Correct.

> **···**
>
> On May 30, 2007, at 19:29, Erwin Abbott wrote:

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [31 May 2007 07:12 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/3 "2007-05-31T07:12:24Z")

</div>

> I've been reading about DRb and one issue that I still have questions  
> about is thread safety. Every website I've come across uses very  
> basic examples where the client never does anything that would modify  
> the distributed object.

There's some examples which do this at  
[http://wiki.rubygarden.org/Ruby/page/show/DRbTutorial](http://wiki.rubygarden.org/Ruby/page/show/DRbTutorial)

Unfortunately Rubygarden is down more often than it's up (it's down as I  
write this), but you can get a cached version through Google.

> For sake of discussion, let's say I'm writing an application that's  
> some kind of database. Clients can add, delete, search, or modify  
> records. How can this be written so clients can't step on each other,  
> or block the whole database while perfoming and update on a single  
> record?

Well, that's the general locking problem in a nutshell, and many books have  
been written about this 🙂

The solution will be domain-specific. The simplest solution is to serialise  
all requests on the server side using a global mutex:

class DatabaseServer  
&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;@mutex = Mutex.new  
&nbsp;&nbsp;end

&nbsp;&nbsp;def add(r)  
&nbsp;&nbsp;&nbsp;&nbsp;@mutex.synchronize do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# stuff  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

&nbsp;&nbsp;def search(r)  
&nbsp;&nbsp;&nbsp;&nbsp;@mutex.synchronize do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# stuff  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

&nbsp;&nbsp;# etc  
end

This is a reasonable approach if all the actions like add, search are  
CPU-bound, because having concurrency here won't gain you anything.

If some of these actions can block on external I/O, then you might want to  
have more concurrency. So you can look at having a shared read lock /  
exclusive write lock kind of model; or you can push the problem downstream  
(that is, write your app using some pre-existing thread-safe backend store,  
and then just let multiple clients run your code concurrently)

B.

> **···**
>
> On Thu, May 31, 2007 at 11:29:46AM +0900, Erwin Abbott wrote:

---

<div class="post-metadata">

**Author:** ![Marcin\_Raczkowski1](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@Marcin\_Raczkowski1](https://rubytalk.org/u/Marcin_Raczkowski1)\
**Post date:** [31 May 2007 09:42 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/4 "2007-05-31T09:42:51Z")

</div>

Rinda::TupleSpace is just an array of arrays with few sophisticated functions  
that let you find tuples (arrays) with one element matching.

if you want thread safety write your own monitors or just use mutexes

also you can use already thread safe classes like Queue

greets

> **···**
>
> On Thursday 31 May 2007 02:29, Erwin Abbott wrote:
> 
> > I've been reading about DRb and one issue that I still have questions  
> > about is thread safety. Every website I've come across uses very  
> > basic examples where the client never does anything that would modify  
> > the distributed object.
> > 
> > For sake of discussion, let's say I'm writing an application that's  
> > some kind of database. Clients can add, delete, search, or modify  
> > records. How can this be written so clients can't step on each other,  
> > or block the whole database while perfoming and update on a single  
> > record? Having a mutex for every record doesn't seem very elegant.
> > 
> > I'm also still getting aquainted with threads, and I want to be sure I  
> > have this right: each thread has it's own "local" variables, so if two  
> > threads have access to the same array and they both call array.max...  
> > any local vars used in the #max method won't be "stepped on" by the  
> > other thread. As long as #max doesn't change any variables outside its  
> > method scope, it will be thread safe?
> > 
> > Thanks,  
> > &nbsp;&nbsp;Erwin
> 
> --  
> Marcin Raczkowski  
> ---  
> Friends teach what you should know  
> Enemies Teach what you have to know

---

<div class="post-metadata">

**Author:** ![Erwin\_Abbott](https://avatars.discourse-cdn.com/v4/letter/e/4af34b/32.png) [@Erwin\_Abbott](https://rubytalk.org/u/Erwin_Abbott)\
**Post date:** [31 May 2007 08:04 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/5 "2007-05-31T08:04:11Z")

</div>

Hi Eric, I was hoping you would respond (I came across your site and a  
few discussions on ruby-talk while researching DRb)! From what I've  
read about Rinda::TupleSpace, it seems similar to a Queue. The  
difference, as far as I understand, is the idea of a template that  
lets us choose to only pop certain kinds of items off the queue  
(instead of maintaining several different queues). Maybe you can fill  
me in if I overlooked something, I'm not familiar with Linda so the  
whole idea is a bit foreign to me.

I'm probably just not developed the mindset for using TupleSpaces yet,  
but I've only seen examples where some data is sent off to some  
"worker bee" client, and then it's written back to the TupleSpace. I'm  
pretty sure I understand those examples but I can't figure out how  
this will apply to my application.

I'm hoping to be able to do something like db.search(params) =\> [a, b,  
c, d, ...] where this is an array of records. Then calling methods  
that modify the record like a.delete! or a.name = 'Harry' would take  
care of locking the record. Calling db.store Record.new(1, 2, 3) would  
add a new record to the database. Of course "db" is the object  
connected with DRb.

Maybe you can give a brief explanation of how to use Rinda::TupleSpace  
in this case? I can maybe see records being stored on the TupleSpace  
when they are updated, but I don't really get it yet. Would searches  
be done using ts.read using the template to provide search parameters?  
I was thinking the "database" object would be more abstract than a big  
table of records, so comparing "fields" with == or === might not be  
flexible enough (that's how the templates are matched, right?). Maybe  
it's an address book, and there's a method to find customers that  
haven't payed their bills from last month?

- Erwin

> **···**
>
> On 5/30/07, Eric Hodel \<drbrain@segment7.net\> wrote:
> 
> > Having your database be a Rinda::TupleSpace is one way around it.

---

<div class="post-metadata">

**Author:** ![Erwin\_Abbott](https://avatars.discourse-cdn.com/v4/letter/e/4af34b/32.png) [@Erwin\_Abbott](https://rubytalk.org/u/Erwin_Abbott)\
**Post date:** [31 May 2007 08:31 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/6 "2007-05-31T08:31:53Z")

</div>

> There's some examples which do this at  
> [http://wiki.rubygarden.org/Ruby/page/show/DRbTutorial](http://wiki.rubygarden.org/Ruby/page/show/DRbTutorial)
> 
> Unfortunately Rubygarden is down more often than it's up (it's down as I  
> write this), but you can get a cached version through Google.

Glad you mentioned the Google cache... I kept finding links to that  
page and wondered what I was missing. I'll be reading that next.

> Well, that's the general locking problem in a nutshell, and many books have  
> been written about this 🙂

I'm very interested in a book on programming with threads, any  
recommendations? I'll probably browse the bookstore this weekend. I'm  
afraid everything will be focused on specifics like language/OS rather  
than general concepts. It's also hard to know what's good from reading  
reviews on Amazon.

> The solution will be domain-specific. The simplest solution is to serialise  
> all requests on the server side using a global mutex:
> 
> This is a reasonable approach if all the actions like add, search are  
> CPU-bound, because having concurrency here won't gain you anything.

The reason for using synchronization in #search is because we might  
start in the middle of a #write call from another thread, right? I had  
something in mind like an SQL database which would search using the  
"not-yet-written" version of the data... but now I think I see that's  
quite complicated.

I also think I just came to a realization. In the threading examples  
I've seen, there's typically a "sleep 5" as a placeholder for some big  
computation. But this simulates an I/O bound process instead of  
something computationally intesive. So processing 10 items each with  
their own thread (which just sleeps for 5 seconds) will finish in  
close to 5 seconds... a huge improvement over processing them  
serially. But processing the items was actually CPU intensive, would  
it be more like 50 seconds?

> If some of these actions can block on external I/O, then you might want to  
> have more concurrency. So you can look at having a shared read lock /  
> exclusive write lock kind of model; ...

I'd like to learn the design concepts involved with that, just to gain  
an appreciation for the complexity of it. Is my best bet to look at  
the source code of something like an SQL server? Maybe one of the  
Berkeley DB variants or SQLite would be a good starting point (or  
maybe a multiuser DB if these aren't multithreaded). Thanks for your  
help!

Erwin

> **···**
>
> On 5/31/07, Brian Candler \<B.Candler@pobox.com\> wrote:

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [31 May 2007 10:51 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/7 "2007-05-31T10:51:30Z")

</div>

> \>Well, that's the general locking problem in a nutshell, and many books have  
> \>been written about this 🙂
> 
> I'm very interested in a book on programming with threads, any  
> recommendations? I'll probably browse the bookstore this weekend. I'm  
> afraid everything will be focused on specifics like language/OS rather  
> than general concepts. It's also hard to know what's good from reading  
> reviews on Amazon.

I have a good book on principles of operating systems which talks a lot  
about synchronisation; unfortunately it's in a different location right now  
and I can't remember the exact title. It's pretty old.

> The reason for using synchronization in #search is because we might  
> start in the middle of a #write call from another thread, right? I had  
> something in mind like an SQL database which would search using the  
> "not-yet-written" version of the data... but now I think I see that's  
> quite complicated.

No, that's quite doable as well. What you need to do is to protect the part  
where you replace @data with new\_data, to ensure there are no readers of  
@data while you're changing it.

To do this you need a shared lock for the readers, and for the writer to  
gain an exclusive lock at the point where it wants to swap the data. While  
any shared locks are held, the exclusive lock will not be granted; and while  
an exclusive lock is held no shared or exclusive locks will be granted.

Have a look at sync.rb in the standard Ruby distribution, although I've not  
used it in anger myself. Something like this might do the trick:

require 'sync'

class DatabaseServer

&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;@sync = Sync.new  
&nbsp;&nbsp;&nbsp;&nbsp;@data = {}  
&nbsp;&nbsp;end

&nbsp;&nbsp;def search(k)  
&nbsp;&nbsp;&nbsp;&nbsp;@sync.synchronize(Sync::SH) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Reading..."  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Read done"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@data[k]  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;end

&nbsp;&nbsp;def update(k,v)  
&nbsp;&nbsp;&nbsp;&nbsp;@sync.synchronize(Sync::EX) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Updating..."  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@data[k] = v  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep 2  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Update done"  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;end  
end

d = DatabaseServer.new

t1 = Thread.new {  
&nbsp;&nbsp;sleep 0.5  
&nbsp;&nbsp;d.update("foo","bar")  
}  
t2 = Thread.new {  
&nbsp;&nbsp;puts "t2(a): #{d.search("foo")}"  
&nbsp;&nbsp;puts "t2(b): #{d.search("foo")}"  
}  
t1.join  
t2.join

Note that this is an artificial example, since reading an element from a  
hash or writing an element to a hash are 'atomic' operations as far as the  
Ruby thread scheduler is concerned. That is, in this simplistic case,  
everything will work fine without explicit synchronisation. But as soon as  
your searches or updates become multi-step operations (e.g. a search  
involves a lookup in index I followed by a read of record R) then you need  
this, so that for any particular operation, the index and the records are in  
a consistent state throughout. The same applies for write-after-read  
operations, such as @id=@id+1.

You'll also need to be careful about what you return to your clients. Don't  
return a reference to some object which may be mutated later; use 'dup' to  
make a copy for the client if necessary.

> I also think I just came to a realization. In the threading examples  
> I've seen, there's typically a "sleep 5" as a placeholder for some big  
> computation. But this simulates an I/O bound process instead of  
> something computationally intesive. So processing 10 items each with  
> their own thread (which just sleeps for 5 seconds) will finish in  
> close to 5 seconds... a huge improvement over processing them  
> serially. But processing the items was actually CPU intensive, would  
> it be more like 50 seconds?

Yes.

However, using sleep also helps you simulate race conditions, where thread 1  
does X followed by Y, and you want to see what happens if thread 2 does Z in  
between X and Y. That's what I'm using it for above. You can use this to  
demonstrate that two or more threads can successfully obtain a shared lock  
at the same time, for instance.

BTW there's a good introductory chapter in Programming Ruby:  
[http://www.rubycentral.com/book/tut\_threads.html](http://www.rubycentral.com/book/tut_threads.html)

And you might want to look at 'madeleine', which is an in-RAM object  
database written in Ruby.

Regards,

Brian.

> **···**
>
> On Thu, May 31, 2007 at 05:31:53PM +0900, Erwin Abbott wrote:

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [31 May 2007 11:06 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/8 "2007-05-31T11:06:45Z")

</div>

Hmm, the code I gave didn't actually do this 🙂 But it did allow multiple  
readers while there are no changes taking place.

Considering alternatives reveals some of the pitfalls. For example, you can  
conceive of a strategy where the update thread does the following:

1. grabs a shared read lock  
2. makes a local copy of the data and modifies it  
3. upgrades its lock to exclusive  
4. replaces the stored data with its modified copy  
5. drops its lock

However this fails totally if two update threads come along at the same  
time. They both successfully grab the read lock, both make their local  
modifications, and then both hang forever waiting to get an exclusive lock,  
which they can't do while the other still holds a read lock. This is known  
as a "deadlock" scenario.

This is where a good book comes in. There are some relevant articles on  
wikipedia. Googling for "philosophers" and "spaghetti" may also be helpful  
🙂

Regards,

Brian.

> **···**
>
> On Thu, May 31, 2007 at 11:51:27AM +0100, Brian Candler wrote:
> 
> > \> The reason for using synchronization in #search is because we might  
> > \> start in the middle of a #write call from another thread, right? I had  
> > \> something in mind like an SQL database which would search using the  
> > \> "not-yet-written" version of the data... but now I think I see that's  
> > \> quite complicated.
> > 
> > No, that's quite doable as well. What you need to do is to protect the part  
> > where you replace @data with new\_data, to ensure there are no readers of  
> > @data while you're changing it.

---

<div class="post-metadata">

**Author:** ![Erwin\_Abbott](https://avatars.discourse-cdn.com/v4/letter/e/4af34b/32.png) [@Erwin\_Abbott](https://rubytalk.org/u/Erwin_Abbott)\
**Post date:** [1 June 2007 09:42 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/9 "2007-06-01T09:42:59Z")

</div>

Marcin and Brian,

Thank you for the help, I feel like I have a pretty good starting  
place now to figure the details out myself. I'm still not sure what  
the differences between all the data structures like Mutex, Condition  
Variable, Semaphore, Monitor, etc are... but I can work that out.

> This is where a good book comes in. There are some relevant articles on  
> wikipedia. Googling for "philosophers" and "spaghetti" may also be helpful 🙂

Yes, very helpful. It also led me to:  
- Sleeping barber problem  
- Cigarette smokers problem  
- Dining cryptographers protocol

The Concurrency category on Wikipedia should give me plenty to read,  
or at least know what to look for at the bookstore...

> **[Category:Concurrency](https://en.wikipedia.org/wiki/Category:Concurrency)**
>
> The disambiguation article for this category is Concurrency.

Thanks again,  
&nbsp;&nbsp;Erwin

> **···**
>
> On 5/31/07, Brian Candler \<B.Candler@pobox.com\> wrote:

---

<div class="post-metadata">

**Author:** ![Marcin\_Raczkowski1](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@Marcin\_Raczkowski1](https://rubytalk.org/u/Marcin_Raczkowski1)\
**Post date:** [1 June 2007 10:52 UTC](https://rubytalk.org/t/drb-and-thread-safety/37989/10 "2007-06-01T10:52:44Z")

</div>

> Marcin and Brian,
> 
> Thank you for the help, I feel like I have a pretty good starting  
> place now to figure the details out myself. I'm still not sure what  
> the differences between all the data structures like Mutex, Condition  
> Variable, Semaphore, Monitor, etc are... but I can work that out.

Mutex - is block that can't be run concurently  
Semaphore - is like "stop" sign - execution will stop untill semaphore is  
lifted in another thread  
Monitor - is class that throught specially made accessors allows only  
synchronous access to it's methods/variables (Queue class in standard lib is  
good example)  
Condition Variable is something oposite to Semaphore

> \> This is where a good book comes in. There are some relevant articles on  
> \> wikipedia. Googling for "philosophers" and "spaghetti" may also be  
> \> helpful 🙂
> 
> Yes, very helpful. It also led me to:  
> - Sleeping barber problem  
> - Cigarette smokers problem  
> - Dining cryptographers protocol

all these algorithms are very complicated in c - but in ruby are usually  
really easy - you only need to use thread safe classes (like Queue) or  
Monitor mixin

for example in ruby solving Writers and Readers

require 'thread'

bookstore = Queue.new

writers = 4  
readers = 5

writers.times do |w|  
&nbsp;&nbsp;Thread.new {  
&nbsp;&nbsp;&nbsp;&nbsp;5.times { |x|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bookstore.put("new book "+x.to\_s+" by "+w)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep 1+rand(5)  
&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;}  
end

readers.times do  
&nbsp;&nbsp;Thread.new {  
&nbsp;&nbsp;&nbsp;&nbsp;4.times {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts bookstore.pop  
&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;}  
end

> The Concurrency category on Wikipedia should give me plenty to read,  
> or at least know what to look for at the bookstore...  
> [Category:Concurrency - Wikipedia](http://en.wikipedia.org/wiki/Category:Concurrency)

I'm not sure what's the most popular book about algorithmics in you country -  
but try spending some money or go to library ^^

> **···**
>
> On Friday 01 June 2007 09:42, Erwin Abbott wrote:
> 
> > On 5/31/07, Brian Candler \<B.Candler@pobox.com\> wrote:
> 
> > Thanks again,  
> > &nbsp;&nbsp;Erwin
> 
> --  
> Marcin Raczkowski  
> ---  
> Friends teach what you should know  
> Enemies Teach what you have to know
