Monad、Actor與併發編程--基於線程與基於事件的併發編程之爭

將線程、事件、狀態等包裝成流的源。javascript

核心:解決線程的消耗和鎖的效率問題。html

 

Java和Node.js能夠說分別是基於線程和基於事件的兩個併發編程表明,它們互相指責瞧不起對方,讓咱們看看各類陣營的聲音:java

 

基於事件的粉絲認爲線程是一個壞主意,緣由有是:程序員

1. 你得顯式的協調共享數據的鎖,若是你忘記加鎖,你就會獲得中斷壞的數據。編程

2. 依賴鎖致使死鎖。服務器

3. 它們難以調試多線程

4. 回調並無鎖併發

5. 多線程在多核上的性能並不會比每一個單核一個線程性能更好。app

 

你應當儘量地避免線程,對於GUI和分佈式系統或低端服務器不要用線程,只有處理CPU併發時才須要線程,若是必須使用線程,將線程隔離在覈心內部,讓大部分代碼保持單線程。異步

 

而基於線程的粉絲認爲Why events are a bad idea,反駁理由是:

1. 不少使用線程實現高併發卻沒有得到好性能?這其實假象,有人建立一個可擴展到100,000的線程庫,其性能匹配SEDA的基於事件實現的性能。

2.線程限制流程控制?線程派分析了基於事件的系統, 發現這些應用控制流程模式有三種:call-return, parallel calls和 pipeline. 這些都很容易使用線程表達。

3.線程同步鎖過重量?協調式多任務(協程)能讓線程輕量等同於基於事件的併發。

4.線程堆棧沒有足夠效率管理活動狀態?不是,一個新的動態增加性堆棧stack模型能夠解決這個問題。

5.線程會阻止運行時刻進行優化調度決定?不是這樣,Lauer 和Needham 都顯示不是這種狀況。

線程派認爲現代服務器雖然須要併發處理大量的請求,可是代碼處理每一個請求一般是有順序的,咱們相信線程提供這兩種狀況下很好的編程抽象。

儘管事件系統在高併發下有很好的性能,可是咱們已經證實使用線程也會有相似性能(banq注:不過真的須要高手),因爲語言提供編譯時的分析使得線程簡單,同樣和基於事件系統能實現高併發。

 

線程派的改良表明能夠首推Go的Goroutine和Python的coroutine協程,它們解決了直接基於OS線程致使線程上下文切換時帶來的性能損耗,並且經過調度器保證非堵塞。Goroutine最大的特色可以讓程序員以同步順序代碼的風格編寫異步運行,Goroutine=coroutine協程 + user space threads + fibers + greenlets。由於綠色線程被封裝在語言的API中,所以相比Node.JS顯式處理異步IO,GO語言提供了隱式的異步處理IO,從而使得併發異步變得簡單。

 

在GO語言的競爭之下,Node.JS一直探索如何避免回調陷阱,從Promise 到coroutine/Generators,直至演化到Javascript 7的async函數。從而也能夠實現使用熟悉的順序編程風格編寫出異步代碼,下面是使用JS 7的新的異步函數:

 

 

function* getStockPrice(name) {
    var symbol = yield getStockSymbol(name);
    var price = yield getStockPrice(symbol);
    return price;
}
var result = 
    spawn(getStockPrice.bind(null, "Pfizer"));
result.then(console.log, console.error);

<p>

 

Javascript 7主要亮點是在事件機制和異步編程的提高上,這兩點主要體如今:

1. Object.observe使得模型和視圖之間很容易同步。

2. async函數更易於異步編程,可以實現拉Pull或推Push。

 

http://www.jdon.com/idea/js/javascript7.html

 

以Node.js爲主的事件派和Go的協程派打得熱乎時,這時有了一種觀點,既然大家二者都回避各自缺陷表現得不錯,下面是就剩下使用者的愛好和技能選擇了,能不能提供一種語言將這二者結合在一塊兒?

 

Haskell倡導者提出經過語言統一多線程編程和事件編程,提供一種Monad函數,其內部封裝了事件和多線程抽象,不管你是哪派粉絲,均可以使用這個Monad編程。以下圖:A language-based approach to unifying events and threads

 


 

這種觀點獲得大多數人的贊成,這時被冷落一邊的Scala的Actor模型站出來認爲本身的Actor函數屬於這種二者合一的Monad函數,見這裏

 

固然,Go的綠色線程Goroutine與Actor仍是有區別的:Actor模型和CSP模型的區別

 

縱觀併發編程發展,你們都是從IO這個串行化端口入手,神仙過海,各顯神招,從當初Java的NIO 到Node.JS的異步IO 再到Go的Goroutine以及Netty 以及Actor模型等等,應該說,誰在Socket IO這個戰場上性能和易用性表現得更好,誰就可能在併發編程整個領域得到全勝。

 

https://www.jdon.com/46921

相關文章
相關標籤/搜索