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!