通常來講有兩種策略用來在併發線程中進行通訊:共享數據和消息傳遞。使用共享數據方式的併發編程面臨的最大的一個問題就是數據條件競爭。處理各類鎖的問題是讓人十分頭痛的一件事。java
傳統多數流行的語言併發是基於多線程之間的共享內存,使用同步方法防止寫爭奪,Actors使用消息模型,每一個Actor在同一時間處理最多一個消息,能夠發送消息給其餘Actor,保證了單獨寫原則。從而巧妙避免了多線程寫爭奪。和共享數據方式相比,消息傳遞機制最大的優勢就是不會產生數據競爭狀態。實現消息傳遞有兩種常見的類型:基於channel(golang爲典型表明)的消息傳遞和基於Actor(erlang爲表明)的消息傳遞。golang
Actor模型(Actor model)首先是由Carl Hewitt在1973定義, 由Erlang OTP 推廣,其 消息傳遞更加符合面向對象的原始意圖。Actor屬於併發組件模型,經過組件方式定義併發編程範式的高級階段,避免使用者直接接觸多線程併發或線程池等基礎概念。Actor模型=數據+行爲+消息。redis
Actor模型是一個通用的併發編程模型,而非某個語言或框架全部,幾乎能夠用在任何一門編程語言中,其中最典型的是erlang,在語言層面就提供了Actor模型的支持,殺手鐗應用RabbitMQ 就是基於erlang開發的。編程
Actor相似面向對象編程(OO)中的對象,每一個Actor實例封裝了本身相關的狀態,而且和其餘Actor處於物理隔離狀態。舉個遊戲玩家的例子,每一個玩家在Actor系統中是Player 這個Actor的一個實例,每一個player都有本身的屬性,好比Id,暱稱,攻擊力等,體現到代碼級別其實和咱們OO的代碼並沒有多大區別,在系統內存級別也是出現了多個OO的實例緩存
class PlayerActor { public int Id { get; set; } public string Name { get; set; } }
在使用Java/C# 等語言進行併發編程時須要特別的關注鎖和內存原子性等一系列線程問題,而Actor模型內部的狀態由它本身維護即它內部數據只能由它本身修改(經過消息傳遞來進行狀態修改),因此使用Actors模型進行併發編程能夠很好地避免這些問題。Actor內部是以單線程的模式來執行的,相似於redis,因此Actor徹底能夠實現分佈式鎖相似的應用。服務器
每一個Actor都有一個專用的MailBox來接收消息,這也是Actor實現異步的基礎。當一個Actor實例向另一個Actor發消息的時候,並不是直接調用Actor的方法,而是把消息傳遞到對應的MailBox裏,就好像郵遞員,並非把郵件直接送到收信人手裏,而是放進每家的郵箱,這樣郵遞員就能夠快速的進行下一項工做。因此在Actor系統裏,Actor發送一條消息是很是快的。網絡
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vWwNZ5t0-1570964270753)(https://timgsa.baidu.com/timg...]多線程
這樣的設計主要優點就是解耦了Actor,數萬個Actor併發的運行,每一個actor都以本身的步調運行,且發送消息,接收消息都不會被阻塞。架構
每一個Actor的實例都維護這本身的狀態,與其餘Actor實例處於物理隔離狀態,並不是像 多線程+鎖 模式那樣基於共享數據。Actor經過消息的模式與其餘Actor進行通訊,與OO式的消息傳遞方式不一樣,Actor之間消息的傳遞是真正物理上的消息傳遞。併發
每一個Actor實例的位置透明,不管Actor地址是在本地仍是在遠程機器上對於代碼來講都是同樣的。每一個Actor的實例很是小,最多幾百字節,因此單機幾十萬的Actor的實例很輕鬆。若是你寫過golang代碼,就會發現其實Actor在重量級上很像Goroutine。因爲位置透明性,因此Actor系統能夠隨意的橫向擴展來應對併發,對於調用者來講,調用的Actor的位置就在本地,固然這也得益於Actor系統強大的路由系統。
每一個Actor實例都有本身的生命週期,就像C# java 中的GC機制同樣,對於須要淘汰的Actor,系統會銷燬而後釋放內存等資源來保證系統的持續性。其實在Actor系統中,Actor的銷燬徹底能夠手動干預,或者作到系統自動化銷燬。
說到Actor的容錯,不得不說仍是挺使人意外的。傳統的編程方式都是在未來可能出現異常的地方去捕獲異常來保證系統的穩定性,這就是所謂的防護式編程。可是防護式編程也有本身的缺點,相似於現實,防護的一方永遠不能100%的防護住全部未來可能出現代碼缺陷的地方。好比在java代碼中不少地方充斥着判斷變量是否爲nil,這些就屬於防護式編碼最典型的案例。可是Actor模型的程序並不進行防護式編程,而是遵循「任其崩潰」的哲學,讓Actor的管理者們來處理這些崩潰問題。好比一個Actor崩潰以後,管理者能夠選擇建立新的實例或者記錄日誌。每一個Actor的崩潰或者異常信息均可以反饋到管理者那裏,這就保證了Actor系統在管理每一個Actor實例的靈活性。
天下無完美的語言,框架/模型亦是如此。Actor做爲分佈式下併發模型的一種,也有其劣勢。
搜索公衆號:架構師修行之路,領取福利,獲取更多精彩內容