This might be premature optimization, or premature over-cautionization, but I'm avoiding using singletons on a few classes because I'm concerned that down the road I'll need to run my app as multi-threaded, and 开发者_Go百科that the singletons will create conflicts and messiness. Do singletons have this issue in Ruby, or is there some kind of built in namespace so that when an a class refers to the singleton, only the singleton on the same thread is returned?
Edit: to clarify these are observable classes which when updated cause the other classes that are watching them to update. I'm not sure if this is thread safe or not, but I do know that right now I'm passing these observable classes around a ton and it's kind of annoying. And they do seem like natural singleton classes.
Here is an example of making a singelton threadsafe. You have to treat it like any other object which has state (@things
) and is not immutable (readonly). The getters and setters need to access the internal state via a Mutex (mutual exclusion).
require 'singleton'
class MyObject
include Singleton
def initialize
@things = []
@mutex = Mutex.new
end
def add(thing)
with_mutex { @things << thing }
end
def things
with_mutex { @things }
end
def clear
with_mutex { @things.clear }
end
def self.add(thing)
instance.add(thing)
end
def self.things
instance.things
end
def self.clear
instance.clear
end
private
def with_mutex
@mutex.synchronize { yield }
end
end
Further reading: http://rubylearning.com/satishtalim/ruby_threads.html
All classes that aren't written to be thread-safe will cause problems in a multi-threaded environment, regardless of whether they're singletons or not.
The fact that your class is a singleton could make the problem worse, because it's shared by default. You can't have an instance per-thread.
If the singleton state is read-only and immutable you won't have a thread safety issue.
If shared state is modified, you have to ensure that it's thread safe.
Although this seems like a case of YAGNI, the Singleton class does require thread
and states the following in the docs:
Klass._instantiate?() - returning ``the instance’’ or nil. This hook method puts a second (or nth) thread calling Klass.instance() on a waiting loop. The return value signifies the successful completion or premature termination of the first, or more generally, current "instantiation thread".
Does that help?
The Singleton
Ruby mixin itself is thread safe. It means that you are guaranteed to get the same instance in all threads, and only that! It doesn't mean that methods which you implement for a singleton class by yourself will be thread safe.
If you look at the Singleton
module implementation you'll see that #instance
method uses Thread::Mutex#synchronize
to guarantee thread safety of the method itself and also your class #initialize
method. However, keeping your own singleton methods implementation thread safe is your responsibility!
精彩评论