2017-02-08 74 views
1

我的問題可能看起來很奇怪,但我認爲我面臨volatile對象的問題。clojure是「多線程」嗎?

我寫了這樣實現的庫(只是一個方案,而不是真正的內容):

(def var1 (volatile! nil)) 
(def var2 (volatile! nil)) 

(def do-things [a] 
(vreset! var1 a) 
(vswap! var2 (inc @var2)) 
{:a @var1 :b @var2}) 

所以我所計算的全局變量,其被外部值初始化的,別人和我回到自己的內容。 我用揮發性比原子更好的速度,而不是每次重新定義每個計算的新變量。

的問題是,這似乎在實踐中失敗,因爲我map做,事情的集合(在另一個程序中)與內子調用該函數occasionaly,像(僞代碼):

(map 
    (fn [x] 
    (let [analysis (do-things x)] 
     (if blabla 
      (do-things (f x)) 
      analysis)))) coll) 

內部條件調用會在引擎蓋下產生另一個線程嗎?似乎是的,因爲有些事情叫做工作,有時候不行。 除了定義每個do-things機體內部揮發性之外,還有其他什麼方法可以做嗎?

編輯

其實錯誤是另一回事,但問題仍然是在這裏:這是一個可以接受的/安全,沒有對多線程功能的任何顯式調用呢?

回答

9

Clojure中的構造函數很少爲您創建線程 - 通常Clojure可以並將在一個或多個線程上運行,具體取決於您如何構造程序。 pmap是一個很好的例子,它可以創建並管理並行映射的線程池。另一個是clojure.core.reducers/fold,它使用fork/join池,但真的就是這樣。在所有其他情況下,由您來創建和管理線程。

揮發物只應該只有被用於非常小心,並在您控制使用範圍,以確保您不會與線程競爭讀取和寫入相同的易失性的情況下使用。易失性保證可以在另一個線程上讀取寫入,但它們無法保證原子性。爲此,您必須使用原子(用於不協調)或參考和STM(用於協調)。

+0

感謝您的洞察力,它似乎我在另一個代碼的地方犯了一個錯誤,但我仍然不確定什麼是valatiles(文檔有點缺乏),如果它可以安全地在函數範圍外使用它 –