2009-04-10 51 views
2

article指出双重检查锁定是在特定的语言/硬件组合不安全时共享变量可以与到仅部分初始化的对象的引用被更新。Ruby中的双重检查锁定安全吗?

我在想:这是否也适用于Ruby?这是否会因运行的平台上的Ruby实现而有所不同,或者是语言规范中详述的正确行为?

+0

考虑到有多个实现,问题应该指定哪个实现以及哪个底层平台。 – MSalters 2009-04-10 10:47:19

+0

这是一个很好的观点。指示不同实现和平台之间是否存在差异的响应将非常有用。 – Readonly 2009-04-13 06:11:04

回答

4

Ruby的哪个实现? Ruby 1.8,1.9和JRuby具有完全不同的线程实现,因此可能无法说明。

我没有你的问题的答案,但现在看来,你可能试图用Ruby编写的快速并行代码。我对Ruby 1.8的经验是这不是一个合理的目标。 Ruby 1.9可能会更好,但仍然有像Python这样的全局解释器锁。

如果你正在写你在哪里考虑到这些类型的潜在不安全的优化来拧出一些额外的性能Ruby代码,你应该考虑使用另一种语言。习语Ruby倾向于在效率和速度之前强调可读性和表现力。试图扭转速度增加和增加可靠性的核磁共振成为一个锻炼挫折我。

我一直对刚刚进入阶段,我们正在认真看着优化Ruby项目一段时间。在JRuby中运行项目并用Java库替换Ruby中实现的瓶颈,导致速度和可靠性的显着提高,而我们的努力相对较少。

JRuby是不完美的,但它的Java集成已被证明是有益的和容易。如果你的项目不可能使用JRuby,或者你对C但不熟悉Java,并且确信你可以编写安全的C而没有内存泄漏,那么为Ruby 1.8或1.9编写C扩展可能是最佳途径。

我很抱歉如果这个问题是完全学术性的。也许如果你能让我们知道你究竟想做什么?在Java中

+0

这几乎是“完全学术”的性质。我回想起在一些代码中看到一些由多个线程共享的对象的一些懒惰初始化,并回答了这个问题,以便我可以更好地了解是否在未来遇到类似问题。 – Readonly 2009-04-16 17:38:27

4

双重检查是危险的,因为之前的构造函数实际完成值可能会被赋给变量。这在Ruby中不会发生:构造一个对象与将一个函数调用的结果分配给一个变量相同,因为构造函数只是普通的函数。分配只会在构造函数完成后才会发生。

在MRI上,分配是原子的。没有官方的Ruby语言或内存模型规范,但是替代实现倾向于努力模仿MRI的行为,甚至到最晦涩的细节。赋值语句的原子性是一个相当重要的行为,所以我期望其他Ruby实现的赋值也是原子的。

如果你不介意的竞争过程中不小心构建两个对象,一个对象被垃圾收集后,因为它是重复的,那么你可以使用|| =运算符,就像这样:

@singleton ||= FooBar.new 

|| =原子地将给定表达式的结果赋值给变量,但只有在变量尚未设置的情况下。您可以以两个FooBar.new实例结束,但只有一个可以到达。 Ruby on Rails在内部使用这种技术来避免在某些地方使用互斥锁。

0

Dirkjan Bussink(@dbussink)在RubyConf上就此话题发表了演讲。一旦可用,你就想看看他的谈话。

相关问题