Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aren't ruby Queues thread safe why is the queue not synchronizing?

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?

like image 362
MRezk Avatar asked Mar 03 '26 16:03

MRezk


1 Answers

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
like image 50
Stefan Avatar answered Mar 05 '26 12:03

Stefan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!