Reputation: 61
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?
Upvotes: 3
Views: 1088
Reputation: 114178
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
Upvotes: 5