筆記:《七週七併發模型》

漆楚衡發表於2016-04-14

筆記:《七週七併發模型》

書的七部分中,前五部分介紹的都是語言級別的並行與併發,兩部分介紹了特殊裝置(GPU)和計算機叢集兩個角度下的平行計算。

並行與併發引發的問題,根據我現在的理解,分為競爭與通訊。

競爭

競爭在java章節中需要使用鎖進行控制。

而在後續四章中:

  • 函式式設計避免修改資料,消除了競爭;
  • 在需要可變數時,提供了原子變數、agent、STM;
  • Elixir中的actor並不能直接修改其它actor的資料,actor間通訊是由系統信箱維護的;
  • CSP機制與actor異曲同工,執行緒間通訊由第三者(channel)管理。

可以看到後四者提供的程式設計介面都是執行緒安全的,而這些程式設計介面保證使用者程式碼不產生競爭。

通訊

在java章節中,通訊問題通過阻塞佇列解決,並且還可以學到:對於並行演算法,共有資料會成為瓶頸,於是應該儘量線上程本地處理資料,再提供合併機制。當站在叢集的角度看單個計算機,相似觀點催生了最後一部分的MapReduce。

函式式設計中的並行通訊同樣是通過阻塞實現的(future和promise)。

介紹clojure可變數的章節為資料訪問衝突提供了兩種具體方法:

  1. 建立在持久化資料上的重試機制,原子變數和STM。
  2. 非同步化資料寫入,由系統控制真正的寫入過程,agent。

actor模型將通訊問題真正視為通訊,在單一actor(執行緒)的視角,通訊就是接收訊息和發出訊息,訊息的傳遞由系統負責。

CSP與actor類似,線上程間設立通訊物件channel,但是CSP更關注channel上的操作。go塊藉助channel實現了非連續執行的邏輯流程。

總結來看:

  • agent和actor和CSP都通過系統將並行的訪問轉化為序列訪問,於是在使用者看來,世界是序列的。

  • 原子變數、STM、agent是全域性共享資料的安全機制。透過其中儲存的資料也可以實現進度控制。而

  • actor和CSP更關注執行過程,並不設全域性變數,用訊息傳遞一切。

控制反轉

這本書中最使我眼前一亮的莫過於控制反轉的go機制,它使我想到了haskell中的do機制。

go機制與monad其實非常相似,書中go機制所要處理的是回撥困境:需要將一個完整的事務邏輯拆散並嵌入到事務的實現細節當中去。在網頁中,一個多階段的事務(比如,分散在多個顯示頁面中的註冊資訊),執行過程是由使用者主動發起的(點選按鈕進入下一步),在js中的典型解決方案就是回撥,以點選事件為界將完整的邏輯分散到若干個回撥函式中去,這使得實現不能直觀表徵邏輯,即增加了複雜性。

go機制依託降低執行緒成本的底層實現,並以channel抽出了現實流程:通過channel表示滑鼠點選事件,於是就可以在一個邏輯單位(go塊)中描述業務邏輯。

如果需要在haskell中處理相似問題,思路也是相似的。不同之處在與go的底層通過執行緒調整實現了分階段執行(狀態機化),而在haskell中,do機制可以被變換為分散的程式碼塊(可以理解為完整邏輯被haskell拆散並嵌入到實際執行過程中)。

相關文章