2009-04-10 48 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上就此話題發表了演講。一旦可用,你就想看看他的談話。

相關問題