0

我目前正在學習Clojure,並且我不確定如何使用STM來完成併發。我試圖完成的任務非常簡單,我有一個字符串向量,我想同時在每個字符串上運行一個函數,並用該函數返回的字符串替換該字符串。在Clojure中STM的併發性

我目前可以做到這一點很容易與PMAP:

(pmap function string_vector) 

我怎樣才能做到用Clojure使用STM同樣的事情?

+1

我已投票結束這個。這個問題沒有得到很好的解決,因爲它在線程協調領域沒有任何要求,導致STM成爲與解決方案有關的問題。它就像問我怎樣才能用洗碗機吃蘋果? –

回答

2

STM是一種跨線程共享數據的方式。如果你根本不需要進行協調(在這個例子中你不這樣做),那麼使用STM沒有任何真正的理由。

+0

我明白了。我只是想知道學習的目的。我很難理解STM,任何幫助將不勝感激。 – Pythoner

+0

@Pythoner,僅僅因爲它是爲了「學習的目的」並不意味着它不應該是有道理的。你問的是如何說:「我有一架飛機,我怎麼用它來學習駕駛(一輛汽車)?」當然,你可以沿高速公路滑行你的飛機。但是對於駕駛汽車實際上你並不聰明 - 它們是完全不同的機器,具有非常不同的預期用途,並且受到不同的控制。 –

1

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中的其他可變類型處理,原子將是一個很好的選擇。和裁判一起玩也很有趣!玩的開心!

+1

在這裏要小心。既然pmap就像地圖一樣懶惰,你不應該僅僅爲了副作用而對它進行評估,如果你想確保所有的結果都被實現了,那麼就要強制整個事情。如果你沒有碰巧在repl中打印這些變化,那麼這些變化都不會保證發生(事實上,由於分塊,只有前32個變化)。請注意https://gist.github.com/amalloy/906a65d5851ab61554b12482a8dbcb4a中的重複32。 – amalloy

+0

好點! 「懶蟲」在這裏潛伏着。我在裏面放了一個「doall」。還值得注意的是,如果你把dosync放在pmap之外,它不起作用。 –

+2

doall沒有意義。你在一個字符串上調用doall,這是一個無操作。再次嘗試使用超過32個元素的內容,而不將結果打印到repl中以查看是否正確。您需要完成pmap的結果,而不是其中的任何內容。 – amalloy