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?
1 Answers
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.

- 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
-
1Well, 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