iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 4
0

Concurrency V.S. Parallelsim

  • Concurrency 併發:同時管理超過一個任務,但不一定是同時執行,切換前也不必要完成原先的任務。
  • Parallelsim 併行:同時執行超過一個任務。
  • Distributed computing 分布式運算:並行的一個多主機特例。

在 Clojure 中,分布式運算是可以通過庫達成。但在此文,我們講的都是多核心的單一主機的併行。在併發程式設機中,常見的一個情境是阻塞式操作(blocking operation),例如讀取文件,在整個文件讀取完畢前,程式是不會繼續移動的。如果在讀取完畢前,程式就能夠繼續移動,那麼就稱為這是非阻塞,用 Javascript 的術語說,這就叫異步(asynchronously)。

在併發與併行程式設計中,有兩個特別重要的重點:任務分解、風險管理(資料丟失或衝突等)。

Thread

JVM 提供自己的一套線程管理功能。所以,Clojure 是使用線程的。在單處理器的情況下,處理器在多個線程之間來回跳躍處理指令。切換線程的時候,另一個線程也被鎖住了。

Three Concurrency Goblins

  • Reference cell problem 引用單元問題:某儲存位置的值決定於讀寫順序(例如,銀行帳戶)
  • Mutual exclusion 互斥問題:兩個程式同時嘗試往一個位置寫入資訊。若無法鎖死存取權限,會導致內容混亂。
  • Dwarven berserker problem (deadlock) 死鎖問題(進餐哲學家問題)

future

在 Clojure 中,我們若存取一網路資源,例如:

(web-api/get :dwarven-beard-waxes)

程式會暫停以等待完全讀取。不過,我們可以使用 future,使得結果在被真正需要之前可以繼續執行!

(future (Thread/sleep 4000)
        (println "I'll print after 4 seconds"))
(println "I'll print immediately")

理論上,你會先看到 4 seconds 再看到 immediately ,這是因為 sleep 阻斷了繼續逕行。加入了 future 後,阻塞的部分被暫時解除,所以你這次會先看到 immediately 才看到 4 seconds

future list 中的語句,都會被放到新的線程上。使得原本的線程不被阻塞。但是若尚未被執行完,future 會返回當前執行到的最新一行 list 的結果!

(let [result (future (Thread/sleep 3000)
                     (+ 1 1))]
  (println "The result is: " @result)
  (println "It will be at least 3 seconds before I print"))
; => The result is: 2
; => It will be at least 3 seconds before I print

上一篇
Day 03 - Clojure 基礎知識(三)
下一篇
Day 05 - Clojure 基礎知識(五)
系列文
資料科學:使用 Clojure30

尚未有邦友留言

立即登入留言