天天看點

AKKA文檔(java)——術語,概念

原文:http://doc.akka.io/docs/akka/2.3.6/general/terminology.html 譯者:吳京潤

本章我們試圖建立一個通用的術語清單,用來定義有關并發和分布式系統的堅實的基礎,而這也是akka的目标。請注意,在這些術語當中許多并沒有一緻的定義。我們簡單的尋求在akka文檔範圍内使用的工作定義。

并發與并行是相關的概念,但是也有很多細節上的差異。并發意味着兩個或更多的任務正在取得進展,即使它們不是同時執行的。例如,可以用時間片的方式實作這一點,每個任務在時間片内執行一小部分,并與其它任務的切片混合執行。并行的出現使任務實作了真正的同時執行。

如果方法的調用者在方法傳回或抛出異常前不能有任何進展,這個方法調用就被認為是同步的。然而異步調用允許調用者可以取得有限的進展,調用的方法完成時會通過其它機制(可能是注冊的回調、future對象或一條消息)向調用者發送信号。

一個同步api可能使用阻塞方式實作,但這不是必須的。對于一個cpu密集型任務可能有類似的阻塞行為。一般情況下,異步api是更好的選擇,因為它們確定任務可以取得進展。角色是天生異步的,一個角色能夠在發送一條消息後不用等待實際的傳輸行為而繼續執行。

我們談論的阻塞是指一個線程的延遲可以無限期延遲其它一些線程。一個不錯的例子是一個線程以互斥的方式獨占一項資源。如果一個線程無限期的(比如不小心運作了一個無限循環)持有這項資源,而其它線程因等待該資源而無法繼續運作。與此相反,非阻塞意味着沒有線程可以無限期的延遲其它線程。

非阻塞操作比阻塞操作要優先選擇,當系統中包含阻塞操作時,系統整體的進度就不能得到一般性的保證。

死鎖的出現是因為多個參與者同時互相等待對方到達某個特定狀态進而得以繼續,然而它們都因為其它參與者不能到達這個特定狀态(一個“第二十二條軍規”問題)而不能繼續,所有相關子系統都不能被中斷。死鎖與阻塞緊密相關,因為一個參與者線程有能夠無限期延遲其它線程的必要。

發生了死鎖時,沒有參數者可以繼續執行,而饑餓恰好與之相反,當有參與者可以執行時,可能會有一個或更多得不到執行機會。典型場景是一個簡單排程算法問題挑選高優先級任務。如果持續傳入足夠多的高優先級任務,低優先級任務永遠也不會執行。

活鎖類似死鎖,沒有參與者可以繼續執行。所不同的是,不是在等待其它參與者的進度,而是參與者自己不斷改變自己的狀态。一個示例場景是兩個參與者有兩個相同的可用資源。它們都試圖獲得資源,但是它們還會檢查是否有其它參與者也需要這個資源。當資源被其它參與者請求時,它們嘗試得到這個資源的其它執行個體。在不走運的時候,可能會發生兩個競争者在兩個資源之間反彈,永遠也不占有它們,一直遷就于其它參與者。

我們說的競态條件是指有關一組事件的順序的假設可能會受外部不确定性因素的影響。競态條件經常發生在多線程擁有一個共享可變狀态,而線程交替操作引發的意外行為。雖然這是一種常見情況,共享狀态也不必出現競态條件。一個例子是,用戶端向伺服器發送無序資料包(udp資料報就是這樣的例子) p1,p2。資料包可能經由不同的網絡路徑,伺服器可能先收到p2再收到p1。如果消息不包含有關它們的發送順序的資訊,伺服器就不能确定資料包的順序了。依賴于資料包的意義就可能引發競态條件。

注意

akka隻保證在一對給定角色之間傳遞的消息始終保持消息傳遞的順序。見消息傳遞的可靠性。

在前面的章節中,因為一些原因而不推薦阻塞,包括死鎖的危險,降低系統吞吐量。接下來的部分我們從不同程度上讨論多種非阻塞屬性。

無等待

一個無等待的方法是指每次調用確定在有限步驟内結束。如果一個方法是有界無等待的,它的步數就有一個上限。

基于這個定義,無等待方法永遠不阻塞,是以也不會死鎖,因為每一部分都可以在有限步數以後繼續(當調用結束時),無等待方法也不會發生饑餓。

無鎖定

無鎖定屬性比無等待要弱。發生無鎖定的調用時,方法常常在有限步驟内完成。這一定義意味着無鎖定的調用不會發生死鎖。另一方面,確定一些方法在有限步内完成不足以確定所有調用最終都會完成。換句話說,元鎖定不足以確定不會發生饑餓。

無阻塞

無阻塞是本文讨論的比無鎖定還要弱的保證。一個無阻塞的方法調用是指如果有一個隔離執行的時間點(其它線程不執行任何步驟,比如挂起),它在有限步數内結束。所有無鎖定的對象都是無阻塞的,但是反過來通常不成立。

樂觀并發控制(occ)方法通常是無阻塞的。occ的做法是,每一個參與者試圖操作共享對象,但是如果一個參與者探測到與其它參與者沖突,它就復原所有個性,并按照某些排程政策再次嘗試。如果某個時間點上有且隻有一個參與者在嘗試,操作就會成功。