Search code examples
rubymultithreadingthread-safetymetaprogrammingruby-1.9.2

Thread Safety: Class Variables in Ruby


Performing writes/reads on class variables in Ruby is not thread safe. Performing writes/reads on instance variables appears to be thread safe. That said, is it thread safe to perform write/reads on instance variables of a class or metaclass object?

What are the differences between these three (contrived) examples in terms of thread safety?

EXAMPLE 1: MUTUAL EXCLUSION

class BestUser # (singleton class)
  @@instance_lock = Mutex.new

  # Memoize instance
  def self.instance
    @@instance_lock.synchronize do
      @@instance ||= best
    end
  end
end

EXAMPLE 2: INSTANCE VARIABLE STORAGE

class BestUser # (singleton class)
  # Memoize instance
  def self.instance
    @instance ||= best
  end
end

EXAMPLE 3: INSTANCE VARIABLE STORAGE ON METACLASS

class BestUser # (singleton class)
  # Memoize instance
  class << self
    def instance
      @instance ||= best
    end
  end
end

Solution

  • Instance variables are not thread safe (and class variables are even less thread safe)

    Example 2 and 3, both with instance variables, are equivalent, and they are NOT thread safe, like @VincentXie stated. However, here is a better example to demonstrate why they are not:

    class Foo
      def self.bar(message)
        @bar ||= message
      end
    end
    
    t1 = Thread.new do
        puts "bar is #{Foo.bar('thread1')}"
    end
    
    t2 = Thread.new do
        puts "bar is #{Foo.bar('thread2')}"
    end
    
    sleep 2
    
    t1.join
    t2.join
    
    => bar is thread1
    => bar is thread1
    

    Because the instance variable is shared amongst all of the threads, like @VincentXie stated in his comment.

    PS: Instance variables are sometimes referred to as "class instance variables", depending on the context in which they are used:

    When self is a class, they are instance variables of classes(class instance variables). When self is a object, they are instance variables of objects(instance variables). - WindorC's answer to a question about this