Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 
like image 419
Joseph Ravenwolfe Avatar asked Mar 04 '12 19:03

Joseph Ravenwolfe


People also ask

Are class variables thread-safe?

Given the structure of the JVM, local variables, method parameters, and return values are inherently "thread-safe." But instance variables and class variables will only be thread-safe if you design your class appropriately.

Which variables are thread-safe?

On its stack(basically thread stack), local primitives and local reference variables are stored. Hence one thread does not share its local variables with any other thread as these local variables and references are inside the thread's private stack. Hence local variables are always thread-safe.

What is thread-safe in Ruby?

In this approach, the object's state is shared between all threads but the access is limits to a single thread at once. But instead of going that way, you might prefer to use already existing classes such as Concurrent::Array and going with the previous method. A thread-safe subclass of Array.


1 Answers

Examples 2 and 3 are exactly the same. Modules and classes are also objects, and defining a singleton method on a object actually defines it on its singleton class.

With that said, and since you have already established instance variable access is thread safe, examples 2 and 3 are thread safe. Example 1 should also be thread safe, but it is inferior to the other two because it requires manual variable synchronization.

However, if you need to take advantage of the fact that class variables are shared within the inheritance tree, you may have to use the first approach.


The inherent thread safety of the Ruby language depends on the implementation.

MRI, before 1.9, implemented threads at the VM level. This means that even though Ruby is capable of scheduling code execution, nothing is really running in parallel within a single Ruby process. Ruby 1.9 uses native threads synchronized with a global interpreter lock. Only the context which holds the lock may execute code.

n, x = 10, 0  n.times do   Thread.new do     n.times do       x += 1     end   end end  sleep 1 puts x # 100 

The value of x is always consistent on MRI. On JRuby, however, the picture changes. Multiple executions of the same algorithm yielded the values 76, 87, 98, 88, 94. The result could be anything because JRuby uses Java threads, which are real threads and execute in parallel.

Just like in the Java language, manual synchronization is required in order to safely use threads in JRuby. The following code always results in consistent values for x:

require 'thread' n, x, mutex = 10, 0, Mutex.new  n.times do   Thread.new do     n.times do       mutex.synchronize do         x += 1       end     end   end end  sleep 1 puts x # 100 
like image 188
Matheus Moreira Avatar answered Sep 28 '22 00:09

Matheus Moreira