Note: The code summary shown below is not a distillation of the code that I had the problem with. I\'ve left this original summary here since someo
Does it happen with a class variable? @@mutex
. There might be a race condition with making new class-instances between threads and the new copy of @mutex
isn't ready yet. Constants and class variables however, are shared between copies of the class and subclasses. Also, what if you put the @mutex
init code in a memoized method such as:
def self.mutex
@mutex ||= Mutex.new
end
While autoloading is indeed not thread safe in Rails like it is in Ruby 1.9 (per Is autoload thread-safe in Ruby 1.9?), the problem I encountered was not due to that problem and the code I had was not an instance of the code I showed above, but rather an instance of the following:
class Foo
@mutex = Mutex.new
def self.bar
@mutex.synchronize { }
end
end
class Foobar < Foo ; end
Foobar.bar
The problem is that when executing method from a superclass, the value of self
remains unchanged, so the value of @mutex
within Foo.bar
is interpreted in the context of the Foobar
object, not the value of the Foo
object.
This problem can be avoided by using a class variable (e.g. @@mutex
) for the mutex.