在Ruby中将类实例变量用于互斥量 [英] Using class instance variable for mutex in Ruby
问题描述
注意:下面显示的代码摘要不是对我遇到问题的代码的提炼.由于其他人已经回答了,所以我在这里留下了原始摘要,但是我在下面提供的答案中显示了 actual 代码.
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 someone else already answered, but the actual code is shown in the answer I've provided below.
我无法将其隔离到一个失败的小测试用例中,但是以下通用构造使我失败了:
I haven't been able to isolate this to a small failing test case, but I'm getting a failure with the following general construct:
class Foo
@mutex = Mutex.new
....
def self.bar
@mutex.synchronize { ... }
end
end
如果我创建了多个调用Foo.bar
的线程,则有时@mutex
在bar
中将评估为nil
.如果我使用常量(例如MUTEX)而不是实例变量,则不会出现此问题.
If I create multiple threads invoking Foo.bar
, sometimes @mutex
will evaluate to nil
in bar
. If I use a constant (e.g. MUTEX) instead of an instance variable, I don't have this problem.
我不知道它是否重要,但是我正在多核计算机上的JRuby上运行.
I don't know if it's significant, but I'm running on JRuby on a multi-core machine.
对于解决问题的任何解释或帮助,我们将不胜感激.
I'd appreciate any explanation or help in how to isolate the problem.
更新:我相信这与自动加载有关.使用Rails,我可以在Rails从以下目录之一自动加载的目录中重现foo.rb
的以下内容的类似问题:
Update: I believe this is related to autoloading. With Rails, I was able to reproduce a similar problem with the following contents of foo.rb
in one of the directories Rails autoloads from:
class Foo
@mutex = Mutex.new
def self.bar
@mutex.synchronize {}
end
end
然后我在Rails控制台中执行以下操作:
When I then execute the following in the Rails console:
1.upto(4).map { Thread.new { Foo.bar }}.map(&:join)
我收到以下错误:
RuntimeError: Circular dependency detected while autoloading constant Foo
from /Users/palfvin/.rvm/gems/jruby-1.7.10@javlats/gems/activesupport-4.0.1/lib/active_support/dependencies.rb:461:in `load_missing_constant'
from /Users/palfvin/.rvm/gems/jruby-1.7.10@javlats/gems/activesupport-4.0.1/lib/active_support/dependencies.rb:184:in `const_missing'
from (irb):1:in `evaluate'
并且这种行为在CRuby(MRI Ruby)中是相同的.
and this behavior is the same in CRuby (MRI Ruby).
推荐答案
使用类变量会发生这种情况吗? @@mutex
.在线程之间创建新的类实例可能会导致竞争,而@mutex
的新副本尚未准备就绪.但是,常量和类变量在类和子类的副本之间共享.另外,如果将@mutex
初始化代码放在诸如
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
这篇关于在Ruby中将类实例变量用于互斥量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!