假設我有 N 個執行緒訪問一個包含 N 個元素的陣列。陣列在執行緒開始之前就已經準備好了。每個執行緒將訪問不同的元素(執行緒 I 將訪問元素 I,用于讀取和寫入)。
從理論上講,我希望這樣的訪問模式不會導致任何競爭條件,但在這種情況下,Ruby 真的能保證執行緒安全嗎?
uj5u.com熱心網友回復:
但是在這種情況下 Ruby 會真正保證執行緒安全嗎
Ruby 沒有定義的記憶體模型,因此沒有任何形式的保證。
YARV 有一個Giant VM Lock,可以防止多個 Ruby 執行緒同時運行,這提供了一些隱含的保證,但這是 YARV 的私有內部實作細節。例如,TruffleRuby、JRuby 和 Rubinius可以并行運行多個 Ruby 執行緒。
由于沒有規定行為應該是什么,任何 Ruby 實作都可以自由地做任何他們想做的事。最常見的是,Ruby 實作者試圖模仿 YARV 的行為,但即便如此也沒有明確定義。在 YARV 中,資料結構一般不是執行緒安全的,所以如果你想模仿 YARV 的行為,你是否讓所有的資料結構都不是執行緒安全的?但是在 YARV 中,也不能同時運行多個執行緒,所以在很多情況下,操作是隱式執行緒安全的,所以如果你想模仿 YARV,你應該讓你的資料結構執行緒安全嗎?
或者,為了模仿 YARV,是否應該阻止多個執行緒同時運行?但是,能夠并行運行多個執行緒實際上是人們選擇的原因之一,例如 JRuby 而不是 YARV。
如您所見,這不是一個微不足道的問題。
最好的解決方案是分別驗證每個 Ruby 實作的行為。實際上,這是第二好的解決方案。
最好的解決方案是使用并發 ruby?? Gem 之類的東西,其他人已經為您完成了驗證每個 Ruby 實作的行為的作業。Ruby 并發維護者與多個 Ruby 實作有著密切的關系(例如,并發 ruby?? 的兩個主要維護者之一 Chris Seaton 也是 TruffleRuby 的首席開發者,JRuby 核心開發者和 ruby??-core 的成員,例如),因此您通常可以確定并發 ruby?? 中的所有內容在所有支持的 Ruby 實作(當前是 YARV、JRuby 和 TruffleRuby)上都是安全的。
Concurrent Ruby 有一個Concurrent::Array執行緒安全的類。你可以在這里看到它是如何實作的:https : //github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent-ruby/concurrent/array.rb正如你所看到的,對于 YARV,Concurrent::Array實際上是與 相同::Array,但對于其他實作,需要做更多的作業。
并發 ruby?? 開發人員也在致力于指定 Ruby 的記憶體模型,以便在未來,程式員都知道可以期待什么和不可以期待什么,而實作者知道他們可以優化什么,不可以優化什么。
uj5u.com熱心網友回復:
可變陣列的替代品
在標準的 Ruby 實作中,陣列不是執行緒安全的。但是,佇列是。另一方面,Queue 不完全是一個陣列,因此您沒有您可能正在尋找的 Queue 上的所有方法。
在并發紅寶石寶石提供了一個執行緒安全的Array類,但作為一項規則執行緒安全類會比那些不慢。根據您的資料,這可能無關緊要,但這肯定是設計考慮因素。
如果您從一開始就知道將嚴重依賴執行緒,那么您應該在提供并發性和執行緒的 Ruby 實作上構建您的應用程式(例如考慮 JRuby 或 TruffleRuby),并設計您的應用程式以利用或使用其他并發模型將資料視為不可變而不是在執行緒之間共享物件。
不可變資料是比共享物件更好的執行緒模式。如果給予足夠的關注,您可能會或可能不會對任何給定的可變物件有問題,但是與嘗試使可變物件成為威脅安全的相比,Ractors和光纖本地變數應該更快、更安全。但是,YMMV。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/374983.html
上一篇:Pythonkivy更新游戲分數
