Usando variável de instância de classe para mutex no Ruby
Nota: O resumo do código mostrado abaixo énão uma destilação do código que eu tive o problema. Deixei este resumo original aqui desde que alguém já respondeu, mas oreal o código é mostrado na resposta que forneci abaixo.
Não consegui isolar isso em um pequeno caso de teste com falha, mas estou recebendo uma falha com a seguinte construção geral:
class Foo
@mutex = Mutex.new
....
def self.bar
@mutex.synchronize { ... }
end
end
Se eu criar vários threads chamandoFoo.bar
, as vezes@mutex
avaliará paranil
nobar
. Se eu usar uma constante (por exemplo, MUTEX) em vez de uma variável de instância, não tenho esse problema.
Não sei se é significativo, mas estou executando o JRuby em uma máquina com vários núcleos.
Agradeço qualquer explicação ou ajuda em como isolar o problema.
Atualização: acredito que isso esteja relacionado ao carregamento automático. Com o Rails, pude reproduzir um problema semelhante com o seguinte conteúdo defoo.rb
em um dos diretórios que o Rails carrega automaticamente de:
class Foo
@mutex = Mutex.new
def self.bar
@mutex.synchronize {}
end
end
Quando eu executo o seguinte no console do Rails:
1.upto(4).map { Thread.new { Foo.bar }}.map(&:join)
Estou tendo o erro a seguir:
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'
e esse comportamento é o mesmo no CRuby (MRI Ruby).