為什麼現代系統需要新的程式設計模型Akka

2021-09-24 15:23:21 字數 2458 閱讀 4368

akka中最重要的便是actor模型。

幾十年前,carl hewitt提出了actor模型,以作為在高效能網路下並行處理的一種方式。但是在當時並沒有這樣的環境,如今硬體和基礎設施能力已經趕上並超越了carl hewitt當時的預料。所以,那些想構建高效能分布式系統的組織遇到的使用物件導向程式設計(oop)模型無法完全解決的挑戰,現在可以使用actor模型解決。

如今,actor模型不僅被認為是一種高效的解決方案,而且也已經在世界上一些要求苛刻的應用中得到了驗證。為了突出actor模型所能解決的問題,本主題主要討論傳統程式設計思想與現代多執行緒多cpu架構之間的不匹配:

oop的核心是封裝。封裝規定物件內的資料不能直接從外部訪問,只能呼叫方法來進行修改。物件需要暴露出一些安全的操作,這些安全操作用來維護其內部資料的約束。

例如,對有序二叉樹的操作不得違反二叉樹有序的約束。呼叫者希望排序是完整的,當查詢樹中某個資料時,他們需要能夠依賴這個約束。

當我們分析oop執行時行為時,我們有時會繪製乙個時序圖,顯示方法呼叫的互動。

不幸的是,上圖並不能準確地表示執行期間例項的生命週期。實際上,所有這些呼叫發生在同一執行緒上。

當您嘗試模擬多執行緒情況時,上面的這種表達方式就變得更加清晰了。因為我們可以通過下圖來表示兩個執行緒訪問同乙個例項:

兩個執行緒進入同乙個物件相同的方法,但是物件的封裝模型並不能很好的表達這其中發生的事情。兩個執行緒可以以任意方式交錯,想象一下,如果是多執行緒,這個問題會更加嚴重。

解決此問題的常用方法是給這些方法加鎖。雖然這確保了在任何給定時間最多只有乙個執行緒將進入該方法,但這是一種非常昂貴的策略:

這些現實導致了一種尷尬的局面:

此外,鎖只能在本地很好地工作。在協調跨多台機器時,唯一的選擇是分布式鎖。不幸的是,分布式鎖的效率比本地鎖效率要差幾個級別,並且在擴充套件時有更多的限制。分布式鎖需要在多台計算機上通過網路進行多次通訊往返,因此還存在延遲。

在物件導向語言中,我們很少考慮執行緒的執行路徑。我們經常將系統設想為乙個由物件組織成的網路,它們對方法呼叫作出反應,並修改其內部狀態,然後通過方法呼叫相互通訊,從而驅動整個應用程式執行。

但是,在多執行緒分布式環境中,實際上是執行緒通過方法呼叫「遍歷」此物件網路。因此,真正推動應用程式執行的是執行緒:

總結:

在80-90年代的程式設計概念模型中,本地變數是直接寫入到記憶體中的(這和我們理解的本地變數是存在暫存器中是不一樣的)。在現代架構上,cpu是寫入到快取行而不是直接寫入記憶體的。這些快取記憶體大多數都在cpu核心中,也就是說,乙個核心的寫入不會被另乙個核心看到。為了使核心中的本地更改對另乙個核心可見,需要將快取行傳送到另乙個核心中。

在jvm中,我們必須使用volatile標記或使用atomic包裝類明確表示變數要跨執行緒進行記憶體共享。否則,我們只能先加鎖然後訪問它們。為什麼我們不將所有變數都標記為volatile?因為跨核心同步快取行是一項非常昂貴的操作!這樣做會阻止核心去執行額外的工作,並導致快取一致性協議出現瓶頸。

即使對於了解這種情況的開發人員來說,確定哪些變數應該被標記為volatile,或者使用哪種atomic結構也是一種藝術。

總結:

今天,我們將呼叫棧視為理所當然。但是,它們是在乙個併發程式設計並不重要的時代發明的,因為那時多cpu系統並不常見,呼叫棧不會跨執行緒。

當主線程打算將任務委託給「後台」時,這實際上就是將任務委託給另外乙個工作執行緒,實際上就是主線程將乙個任務物件放入工作執行緒中的乙個共享佇列裡,工作執行緒負責從這個佇列裡獲取任務來執行,這就允許主線程繼續前進並執行其他任務。

他的第乙個問題是,工作執行緒如何通知主線程任務已完成?當任務因異常而失敗時會出現更嚴重的問題,異常傳播到**?真實情況是它將傳播到工作執行緒的異常處理程式,然後完全忽略了實際的「呼叫者」是主線程:

這是乙個嚴重的問題。主線程的呼叫棧上不能捕獲這個異常,工作執行緒如何處理這種情況?需要以某種方式通知主線程,例如將異常放在主線程預先準備存放結果的地方,但如果主線程一直沒有收到通知,任務也即丟失!

當工作執行緒在執行任務時出現bug,導致工作執行緒關閉,這時誰來重新啟動乙個執行緒來處理這個任務,並且該任務如何恢復到正常的狀態。這都是問題。

總結:

為什麼需要多執行緒程式設計模型

首先,我們需要多執行緒的主要原因是 在許多應用中會同時發生多種活動,某些活動會隨著時間的推移被阻塞,通過將這些應用程式分解成可以準並行執行的多個順序執行緒,程式設計模型會變得簡單起來。這裡可以說加入了乙個新的元素 並行實體共享同乙個位址空間和所有可用資料的能力。對於某些應用而言,這種能力是必須的,而...

為什麼需要多執行緒程式設計模型

首先,我們需要多執行緒的主要原因是 在許多應用中會同時發生多種活動,某些活動會隨著時間的推移被阻塞,通過將這些應用程式分解成可以準並行執行的多個順序執行緒,程式設計模型會變得簡單起來。這裡可以說加入了乙個新的元素 並行實體共享同乙個位址空間和所有可用資料的能力。對於某些應用而言,這種能力是必須的,而...

為什麼需要日誌審計系統

什麼是日誌 簡單地說,日誌就是計算機系統 裝置 軟體等在某種情況下記錄的資訊。具體的內容取決於日誌的 例如,unix作業系統會記錄使用者登入和登出的訊息,防火牆將記錄acl通過和拒絕的訊息,磁碟儲存系統在故障發生或者在某些系統認為將會發生故障的情況下生成日誌資訊。日誌中有大量資訊,這些資訊告訴你為什...