How does join work on ruby threads?
multithreading, ruby
Solution
Because the `puts "Thread #{i} says #{j} (#{Thread.current})"` part (or perhaps all) of `threads[1]` finished before `puts "After first join"`. The fact that `threads[1].join` was executed after `puts "After first join"` does not affect the result.
You seem to have two points of logic flaw. They should be corrected as follows:
- If `puts "Thread #{i} says #{j} (#{Thread.current})"` of `threads[1]` was done before `puts "After first join"` of the main thread, then whether the entire `threads[1]` was done before `puts "After first join"` started is irrelevant.
- `threads[1]` has chance to be done before `puts "After first join"` of the main thread was executed. `threads[1].join` shows effect only otherwise.
And what is likely to happen (which actually did happen) is that, since you have `threads[0].join` before any `puts` method calls, the main thread was sleeping until `threads[0]` finished. And since `threads[1]`, and `threads[2]` started immediately after `threads[0]`, the three sub-threads finished roughly at almost the same time. In other words, if you wait enough time for `threads[0]` to finish, then it is likely that the other two threads would also be finished.
Problem
Calling `join` on a thread will block the parent thread while the thread to be joined has not finished. To check this, I created this code: ``` threads = [] 3.times do |i| threads << Thread.new do 3.times do |j| puts "Thread #{i} says #{j} (#{Thread.current})" sleep 0.1 end end end #threads.map(&:join) threads[0].join puts "After first join" threads[1].join puts "After second join" threads[2].join puts "Last line of main thread" ``` Running such code gives this output: ``` Thread 0 says 0 (#<Thread:0x007fdceb0b8568>) Thread 2 says 0 (#<Thread:0x007fdce982bb08>) Thread 1 says 0 (#<Thread:0x007fdceb0b8450>) Thread 0 says 1 (#<Thread:0x007fdceb0b8568>) Thread 1 says 1 (#<Thread:0x007fdceb0b8450>) Thread 2 says 1 (#<Thread:0x007fdce982bb08>) Thread 1 says 2 (#<Thread:0x007fdceb0b8450>) Thread 2 says 2 (#<Thread:0x007fdce982bb08>) Thread 0 says 2 (#<Thread:0x007fdceb0b8568>) After first join After second join Last line of main thread ``` Why did ruby print `After first join` after threads' instructions although the instruction `threads[1].join` was executed after this print instruction?