Why is the << operation on an array in Ruby not atomic? Why is the << operation on an array in Ruby not atomic? ruby ruby

Why is the << operation on an array in Ruby not atomic?


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.newproducer = Thread.new do  5.times do |i|    sleep rand(i) # simulate expense    queue << i    puts "#{i} produced"  endendconsumer = Thread.new do  5.times do |i|    value = queue.pop    sleep rand(i/2) # simulate expense    puts "consumed #{value}"  endendconsumer.join


array is your program variable when you apply an operation like << to it. It happens in three-steps:

  • The variable is first copied into a CPU register.
  • The CPU performs computations.
  • The CPU writes back the result to variable memory.

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.