4

Suppose I have a pair of (producer, consumer) YARV threads (Tp,Tc) sharing an Array q - Tp pushes to q, and Tc pops from it. If the order in which the pushes and pops get executed is unimportant, does the code work without any synchronization mechanism?

bsam
  • 880
  • 1
  • 8
  • 18

1 Answers1

3

Accessing arrays is thread-safe in MRI/YARV (and only there) most of the time due to its global interpreter lock (GIL), thus mostly by accident.

You still would have to make sure that you are only performing a single operation each time and avoid read/write constructs. In other Ruby implementations like Rubinius or JRuby, Arrays are explicitly not thread safe.

With that being said, Ruby ships with a different primitive for inter-thread communication, which co-incidentaly is about the only class in MRI/VARV which is explicitly thread-safe: the Queue. It supports pushing and poping objects in a thread-safe way.

Take this example from Ruby's documentation:

queue = Queue.new

producer = Thread.new do
  5.times do |i|
     sleep rand(i) # simulate expense
     queue << i
     puts "#{i} produced"
  end
end

consumer = Thread.new do
  5.times do |i|
     value = queue.pop
     sleep rand(i/2) # simulate expense
     puts "consumed #{value}"
  end
end

There also exists a well-maintained project called concurrent-ruby which offers a lot of powerful primitives for concurrent programming across threads.

Holger Just
  • 52,918
  • 14
  • 115
  • 123
  • Could you explain what you meant by "You still would have to make sure that you are only performing a single operation each time and avoid read/write constructs"? – bsam Aug 13 '18 at 19:28
  • 1
    Well, an operation like `array[0] = array[1] +42 ` is not thread-safe since there could be overlapping threads in between the reads and writes. You also have toi make sure to only access objects stored in the Array / Queue from a single thread at a time (or use a Mutex to enforce this). – Holger Just Aug 13 '18 at 19:32