I am trying to create many threads and return the result in a data structure and I read that Queue is thread-safe, but when I run the code it doesn't produce the expected result.
require 'thread'
class ThreadsTest
queue = Queue.new
threads = []
for i in 1..10
threads << Thread.new do
queue << i
end
end
threads.each { |t| t.join }
for i in 1..10
puts queue.pop()
end
end
The code prints: (always a little different)
4
4
4
4
10
10
10
10
10
10
I was expecting the numbers 1 through 10.
I have tried to synchronize it manually to no avail:
mutex = Mutex.new
for i in 1..10
threads << Thread.new do
mutex.synchronize do
queue << i
end
end
end
What am I missing?
Queue is thread-safe but your code is not. Just like variable queue, variable i is shared across your threads, so the threads refer to the same variable while it is being changed in the loop.
To fix it, you can pass the variable to Thread.new, which turns it into a thread-local variable:
threads << Thread.new(i) do |i|
queue << i
end
The i within the block shadows the outer i, because they have the same name. You can use another name (e.g. |thread_i|) if you need both.
Output:
3
2
10
4
5
6
7
8
9
1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With