# Understanding Threads

**URL:** <https://www.ruby-forum.com/t/understanding-threads/178713>\
**Category:** Ruby\
**Created:** [November 9, 2009, 9:45pm UTC](https://www.ruby-forum.com/t/understanding-threads/178713 "2009-11-09T21:45:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 9, 2009, 9:45pm UTC](https://www.ruby-forum.com/t/understanding-threads/178713/1 "2009-11-09T21:45:57Z")

</div>

I am writing an app that retrieves multiple web pages in one method  
call. Threading has improved performance drastically for me, but I  
need some help understanding how exactly the call to join is going to  
affect my program.

Here’s some code:

def method(string)  
result = {}  
mutex = Mutex.new  
threads = []

%w{methodname1 methodname2 methodname3 methodname4}.each do |method|  
threads \<\< Thread.new(method) do |m|  
r = eval("#{m}(string)") # each method call makes an HTTP  
request  
mutex.synchronize { result.merge!® }  
end  
end  
threads.each { |t| t.join }  
result  
end

Seems like the call to join on each thread is necessary to keep the  
script from getting ahead of itself, but if I exclude that line, it  
doesn’t seem to hurt my results and the program runs a lot faster.  
Also, sometimes I get deadlocked somehow if I do use the call to join  
and I’m not certain as to why. Can someone help shed some light on the  
situation? Do I need to call join? Any idea why I’m deadlocking?  
Thanks!

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 9, 2009, 10:15pm UTC](https://www.ruby-forum.com/t/understanding-threads/178713/2 "2009-11-09T22:15:13Z")

</div>

On Mon, Nov 9, 2009 at 3:45 PM, Matt W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> threads = []  
> end
> 
> Seems like the call to join on each thread is necessary to keep the  
> script from getting ahead of itself, but if I exclude that line, it  
> doesn’t seem to hurt my results and the program runs a lot faster.  
> Also, sometimes I get deadlocked somehow if I do use the call to join  
> and I’m not certain as to why. Can someone help shed some light on the  
> situation? Do I need to call join? Any idea why I’m deadlocking?  
> Thanks!

Thread#join simply says “Wait here until this thread has finished  
executing”.

So what you’re doing is waiting for all threads to finish before  
execution  
continues, aka blocking main thread execution. Without the #join, the  
values  
in results will be nonderministic. Any perceived deadlocking is probably  
whatever is in your eval call not timing out. You’ll have to watch out  
carefully for that.

Jason

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 9, 2009, 11:02pm UTC](https://www.ruby-forum.com/t/understanding-threads/178713/3 "2009-11-09T23:02:37Z")

</div>

On 11/09/2009 10:24 PM, Judson L. wrote:

> end  
> Even better: we have Thread.value. If you join only from a single  
> thread there is no additional synchronization needed:

irb(main):001:0\> t = (1…5).map {|i| Thread.new(i) {|x| “value #{x}”} }  
=\> [#\<Thread:0x9c4f618 dead\>, #\<Thread:0x9c4f58c dead\>,  
#\<Thread:0x9c4f4b0 run\>, #\<Thread:0x9c4f424 run\>, #\<Thread:0x9c4f398  
run\>]  
irb(main):002:0\> t.map {|th| th.value}  
=\> [“value 1”, “value 2”, “value 3”, “value 4”, “value 5”]

> And exception handling, etc, will be ever so much clearer.  
> You can as well do

def method(string)  
threads = %w{  
methodname1  
methodname2  
methodname3  
methodname4  
}.map do |method|  
Thread.new(method) do |m|  
send(m, string) # each method call makes an HTTP request  
end.map {|th| th.value}  
end

and be done.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 9, 2009, 10:25pm UTC](https://www.ruby-forum.com/t/understanding-threads/178713/4 "2009-11-09T22:25:10Z")

</div>

I completely agree with Jason’s diagnosis. I’d like to make two  
observations, though.

First, you can avoid the mutex entirely by using thread-local variables:

threads \<\< Thread.new { Thread.current[:result] = method1(string) }

results = threads.inject({}) do |results, thread|  
thread.join  
results.merge(thread[:result])  
end

Second, and (possibly) more controversially, just because you can eval  
doesn’t mean you should. To my eye, this looks nicer:

threads = [  
Thread.new { Thread.current[:result] = method1(string) },  
Thread.new { Thread.current[:result] = method2(string) },  
Thread.new { Thread.current[:result] = method3(string) },  
Thread.new { Thread.current[:result] = method4(string) }  
]

And exception handling, etc, will be ever so much clearer.

Judson
