我目前正在學習Clojure,並且我不確定如何使用STM來完成併發。我試圖完成的任務非常簡單,我有一個字符串向量,我想同時在每個字符串上運行一個函數,並用該函數返回的字符串替換該字符串。在Clojure中STM的併發性
我目前可以做到這一點很容易與PMAP:
(pmap function string_vector)
我怎樣才能做到用Clojure使用STM同樣的事情?
我目前正在學習Clojure,並且我不確定如何使用STM來完成併發。我試圖完成的任務非常簡單,我有一個字符串向量,我想同時在每個字符串上運行一個函數,並用該函數返回的字符串替換該字符串。在Clojure中STM的併發性
我目前可以做到這一點很容易與PMAP:
(pmap function string_vector)
我怎樣才能做到用Clojure使用STM同樣的事情?
STM是一種跨線程共享數據的方式。如果你根本不需要進行協調(在這個例子中你不這樣做),那麼使用STM沒有任何真正的理由。
我明白了。我只是想知道學習的目的。我很難理解STM,任何幫助將不勝感激。 – Pythoner
@Pythoner,僅僅因爲它是爲了「學習的目的」並不意味着它不應該是有道理的。你問的是如何說:「我有一架飛機,我怎麼用它來學習駕駛(一輛汽車)?」當然,你可以沿高速公路滑行你的飛機。但是對於駕駛汽車實際上你並不聰明 - 它們是完全不同的機器,具有非常不同的預期用途,並且受到不同的控制。 –
clojure中的STM是關於隨着時間的推移維持可變物的狀態。這些狀態每時每刻都在變化的事物被認爲具有「身份」。正如你一生中擁有「你」的身份一樣,即使三個月大的「你」在120歲時也不會承認「你」。所以讓我們把東西可變在你的榜樣,所以我們有藉口使用STM:
讓我們做一個公開提供可變的地方來存儲字符串,然後平行改變他們那裏:
user> (def current-strings (ref ["a" "b" "c"]))
#'user/current-strings
user> (dosync (alter current-strings (fn [the-string-at-this-instant]
(pmap #(.toUpperCase %) the-string-at-this-instant))))
("A" "B" "C")
user> @current-strings
("A" "B" "C")
user>
在這例如我們創建了一個事務,通過對其應用一個函數來改變我們字符串集合的狀態。在內部,該函數恰好並行計算新值。
使這更有趣,讓我們做的可變事情載體,然後在並行更新一堆獨立可變的東西每個在它自己的事務:
user> (def current-strings [(ref "a") (ref "b") (ref "c")])
#'user/current-strings
user> (doall
(pmap (fn [ref-to-update]
(dosync (alter ref-to-update #(.toUpperCase %))))
current-strings))
("A" "B" "C")
user> (map deref current-strings)
("A" "B" "C")
user>
正如你所看到的,沒有這需要STM,因爲所有這些操作都可以用clojure中的其他可變類型處理,原子將是一個很好的選擇。和裁判一起玩也很有趣!玩的開心!
在這裏要小心。既然pmap就像地圖一樣懶惰,你不應該僅僅爲了副作用而對它進行評估,如果你想確保所有的結果都被實現了,那麼就要強制整個事情。如果你沒有碰巧在repl中打印這些變化,那麼這些變化都不會保證發生(事實上,由於分塊,只有前32個變化)。請注意https://gist.github.com/amalloy/906a65d5851ab61554b12482a8dbcb4a中的重複32。 – amalloy
好點! 「懶蟲」在這裏潛伏着。我在裏面放了一個「doall」。還值得注意的是,如果你把dosync放在pmap之外,它不起作用。 –
doall沒有意義。你在一個字符串上調用doall,這是一個無操作。再次嘗試使用超過32個元素的內容,而不將結果打印到repl中以查看是否正確。您需要完成pmap的結果,而不是其中的任何內容。 – amalloy
我已投票結束這個。這個問題沒有得到很好的解決,因爲它在線程協調領域沒有任何要求,導致STM成爲與解決方案有關的問題。它就像問我怎樣才能用洗碗機吃蘋果? –