In Ruby, this code is not threadsafe if array
is modified by many threads:
array = []
array << :foo # many threads can run this code
Why is the <<
operation not thread safe?
In ruby '<<' operator is basically used for: Appending a value in the array (at last position) [2, 4, 6] << 8 It will give [2, 4, 6, 8] It also used for some active record operations in ruby.
In standard Ruby implementations, an Array is not thread-safe.
Actually using MRI (Matz's Ruby implementation) the GIL (Global Interpreter Lock) makes any pure C-function atomic.
Since Array#<<
is implemented as pure C-code in MRI, this operation will be atomic. But note this only applies to MRI. On JRuby this is not the case.
To completely understand what is going on I suggest you read these two articles, which explains everything very well:
Nobody Understands the GIL
Nobody Understands the GIL - part 2
If you have multiple threads accessing the same array, use Ruby's built-in Queue class. It nicely handles producers and consumers.
This is the example from the documentation:
require 'thread'
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
consumer.join
array
is your program variable when you apply an operation like <<
to it. It happens in three-steps:
So this high-level single-operation is performed in three steps. In between these steps, due to thread-context switching, other thread may read the same (old) value of the variable. That's why it's not an atomic operation.
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