在 Ruby 中为互斥锁使用类实例变量 [英] Using class instance variable for mutex in Ruby

查看:21
本文介绍了在 Ruby 中为互斥锁使用类实例变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:下面显示的代码摘要不是我遇到问题的代码的提炼.因为其他人已经回答了,所以我把这个原始摘要留在这里,但是实际代码显示在我在下面提供的答案中.

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 初始化代码放在一个 memoized 方法中,例如:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆