C07.共時同作(Concurrency)設計


multi-core processors concurrent programming
多核心處理器共時同作程序設計
  • Concurrency, 共時同作, 並發
如果你想走得快,那麼你就一個人走;如果你想走得遠,那麼就得和一群人一起走。 且貴在堅持到底 !

不需要幾年的時間, 你在學校裡學的軟體工程技術就可能已成為歷史(過時)... 學習 Scala 不研讀其 Concurrency 你就白學了. WisdomFish.ORG

多核CPU要求開發人員必需在函數式編程方面有著堅實的基礎, 而這正式 Scala 的核心價值所在.


多核CPU的來臨







當代與未來的問題


隨著 CPU 多核心的數量不斷上升, 程序不一定執行的更有效率!

在 不久的未來,這情況可能變得更糟。你的順序執行Code不僅不會跑得更快,甚至有可能實際上跑得更慢。其原因在於,你獲得越多的核心,由於對整體耗電率和 散熱的影響,每個核心就會更慢。幾年之後,Intel 就會給我們帶來32核的CPU,按這種趨勢,在我們不知不覺之中數千核的CPU就會出現。但每個核心都會比現在的核心慢很多。


在老舊的程式語言增加新特點, 真的能解決問題?
在 Java中使用有關 Concurrency 特性的學習成本是非常高昂的, Scala 把 Erlang 風格的基於 Actor 的 concurrency 帶進了JVM。開發者現在可以利用 Scala 的 actor 模型在 JVM 上設計具伸縮性的 concurrency 應用程序,它會自動獲得多核心處理器帶來的優勢,而不必依照複雜的Java 線程(Threads)模型來撰寫程序。



一位Twitter工程師的Scala探秘之旅
Actors:處理並發的一個好方法。Scala提供的這個叫做Actor的並行模型通過它的收件箱來發送和接收非同步資訊,而不是共享資料。這種方式被 稱為:shared nothing 模型。一旦你不再顧慮共享資料的問題,也就不必再為代碼同步和死鎖問題而頭痛。




名詞概念


CS 61A Lecture 27: Concurrency I

Concurrency
Parallelism, 平行, 並行



Thread


線程(Thread, 執行緒) 將應用程序劃分成一個或多個同時運行的任務。線程與傳統的多任務進程 之間的區別在於:

  1. 線程共享的是單個進程的狀態資訊,並會直接共享RAM和其他資源。同一個進程中線程之間的上下文切換通常要比進程之間的上下文切換速度更快。
  2. 因此,多線程程序的優點就是它可以比多進程應用程序的執行速度更快。另外,使用線程我們可以實作 Concurrency 處理。


解決方法(Ways)


  1. 撰寫 Thread
    1. 使用線程,但大多數開發者都認為基於線程的應用編寫起來特別的困難。死鎖,餓死以及競爭條件對大多數並發開發者來說都是太熟悉的概念了。Erlang和Scala都大大減輕了這種痛苦。
    2. Scala是站在 JVM之上的,所以一個重要賣點在於可潛在地使用所有現成的Java代碼。然而,大部分的Java代碼並非專為並發而設計的,使用Scala代碼時要將此考慮進去
  2. 使用進程(Process)

其區別之處在於,線程與其它線程之間共享內存,而進程是相互獨立的。這意味著線程需要像互斥信號這樣的鎖機制,防止兩個線程在同一時間對同一內存進行操作,但進程不會受此問題影響,相反是使用一些消息傳遞機制來跟其它的進程間通信。但進程在性能和內存方面的代價是昂貴的,這正是人們就算知道基於線程的並 發是一種極複雜的編程模型也寧願選擇它的原因。





Java Thread 先天問題


Java Thread 為可變物件, 對於一個真實的應用要確保能寫出 Thread 安全的程式碼, 不是不可能, 但極端的困難, 我們可以在許多簡單的例子中就可以看出, 對於 Thread 間對同步程式塊的調用, 都要嚴格的設計 Check, 這是一個很高成本的要求.

immutable object 從根源上解決了這個問題, 沒有狀態能夠被改變, 故也就無需顧慮資料競爭的問題.







輕量級進程


Erlang採取了這樣的並發方式。一個Erlang進程是非常輕量化的,Erlang應用常常擁有成千上萬的線程甚至更多。 Scala通過基於事件的Actor從另一方面達到了同樣的效果。



Scala


  1. Scala有兩種類型的Actor:基於線程或是基於事件。基於線程的Actor在重量級的OS線程內部執行。它們從不相互阻塞,但每個VM上可伸縮的 Actor不會多於幾千個。基於事件的Actor是簡單的物件。它們是十分輕量化的,並且,像Erlang進程一樣,因此它們可以在一台現代的機器上數以百萬計的產生。
  2. 與Erlang進程的區別之處在於,每個OS線程內部,基於事件的Actor是順序執行的並且使用沒有強佔式調度算法。這使得一個基於事件的Actor可能在很長一段時間內阻塞其OS線程(甚至是無限的)。
  3. 大部分Java代碼不可能自動適應Scala的Actor模型。