Pet*_*vin 4 ruby synchronization mutex jruby
注意:下面显示的代码摘要不是我遇到问题的代码的精华.我已经在这里留下了这个原始摘要,因为其他人已经回答了,但实际的代码显示在我在下面提供的答案中.
我无法将其隔离到一个小的失败的测试用例,但我使用以下一般构造失败了:
class Foo
@mutex = Mutex.new
....
def self.bar
@mutex.synchronize { ... }
end
end
Run Code Online (Sandbox Code Playgroud)
如果我创建多个线程调用Foo.bar
,有时@mutex
会评估为nil
在bar
.如果我使用常量(例如MUTEX)而不是实例变量,我没有这个问题.
我不知道它是否重要,但我在一台多核机器上运行JRuby.
我很感激如何解决问题的任何解释或帮助.
更新:我认为这与自动加载有关.使用Rails,我能够使用以下foo.rb
Rails自动加载目录中的以下内容重现类似的问题:
class Foo
@mutex = Mutex.new
def self.bar
@mutex.synchronize {}
end
end
Run Code Online (Sandbox Code Playgroud)
当我在Rails控制台中执行以下操作时:
1.upto(4).map { Thread.new { Foo.bar }}.map(&:join)
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
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'
Run Code Online (Sandbox Code Playgroud)
这个行为在CRuby(MRI Ruby)中是相同的.
它是否发生在类变量中?@@mutex
.可能存在竞争条件,即在线程之间创建新的类实例,而新副本@mutex
尚未准备就绪.但是,常量和类变量在类和子类的副本之间共享.另外,如果将@mutex
init代码放在memoized方法中,例如:
def self.mutex
@mutex ||= Mutex.new
end
Run Code Online (Sandbox Code Playgroud)