根据这个答案,他们是,但随后海报说JRuby中的事情有所不同,所以我很困惑?
我正在使用类实例变量实现多租户解决方案,因此我使用的Ruby实现或Web服务器无关紧要,我需要确保数据不会被泄露.
这是我的代码:
class Tenant < ActiveRecord::Base
def self.current_tenant=(tenant)
@tenant = tenant
end
def self.current_tenant
@tenant
end
end
Run Code Online (Sandbox Code Playgroud)
我需要做些什么才能确保无论发生什么(更改Ruby实现,更改Web服务器,新的Ruby线程功能等),我的代码都是线程安全的?
不确定线程安全是否适用||=.
最初阅读有关ActiveSupport :: Memoizable的内容并且想知道那里的线程安全性.
我有一张有很多预订的餐馆的桌子。现在我想查询所有餐馆,如果他们有 2 人的预订,它应该预加载这些关联。如果没有 2 的预订,它仍应返回餐厅,但关联为空。
为此,我尝试了以下查询:
Restaurant.eager_load(:reservations).where("number_of_people = ?", 2)
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为它会丢弃所有有预订但都不是 2 人的餐厅。
所以我想做的是将该条件移动到连接条件中。就像是:
Restaurant.joins('LEFT OUTER JOIN \"reservations\" ON \"reservations\".\"restaurant_id\" = \"restaurants\".\"id\" AND \"reservations\".\"number_of_people\" = ?', 2)
Run Code Online (Sandbox Code Playgroud)
这将给出我需要的结果,但是这不是预加载“保留”关联而是导致 N+1 问题。
似乎eager_load 不接受自定义查询。我找到了这些线程:https : //github.com/rails/rails/issues/12270和JOIN ON ... AND 在 ActiveRecord 中急切加载关联时的条件,但没有提供解决方案。
注意:下面显示的代码摘要不是我遇到问题的代码的精华.我已经在这里留下了这个原始摘要,因为其他人已经回答了,但实际的代码显示在我在下面提供的答案中.
我无法将其隔离到一个小的失败的测试用例,但我使用以下一般构造失败了:
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.rbRails自动加载目录中的以下内容重现类似的问题:
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)中是相同的.
我的想法是为那些来自java背景的人创建一个社区wiki,因为阅读了大量的解释,直到我真正尝试了几件事情并且拼图的各个部分开始找到他们的位置时,我无法理解任何事情.但我首先需要确保我做对了.从这样的背景来看,我发现这@variable可能意味着两件截然不同的事情让我非常困惑.这是一个例子:
class Test
@ins = "gah"
def self.ins
puts @ins
end
def initialize()
@ins = "wtf?"
end
def ins2
puts @ins
end
end
Run Code Online (Sandbox Code Playgroud)
据我所知,第一个@ins是表示类的对象的实例变量Test.第二个@ins是类对象中的实例变量Test.
现在事情开始对我有意义了.这里有几个例子:
[14] pry(main)> test.ins2
wtf?
Run Code Online (Sandbox Code Playgroud)
我们正在调用一个对象的方法,它返回对象的实例变量.
[15] pry(main)> test.ins
NoMethodError: undefined method `ins' for #<Test:0x000000017d9348 @ins="wtf?">
Run Code Online (Sandbox Code Playgroud)
我们试图通过一个对象调用一个类方法,这个方法属于类,所以我们得到了 NoMethodError
[16] pry(main)> Test.ins
gah
Run Code Online (Sandbox Code Playgroud)
我们正在调用一个类方法,因此它可以正确地看到类对象的实例变量.
[17] pry(main)> Test.ins2
NoMethodError: undefined method `ins2' for Test:Class
Run Code Online (Sandbox Code Playgroud)
我们通过类调用一个对象方法,这是不正确的抛出NoMethodError.
以上所有都是用ruby 2.0进行的.那我在问什么?