From: Judson Lester Date: 2009-11-10T06:24:42+09:00 Subject: Re: Understanding Threads... --0050450176625519ed0477f6d2dc Content-Type: text/plain; charset=UTF-8 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 On Mon, Nov 9, 2009 at 1:14 PM, Jason Roelofs wrote: > On Mon, Nov 9, 2009 at 3:45 PM, Matt White wrote: > > > 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!(r) } > > 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! > > > > > 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 > --0050450176625519ed0477f6d2dc--