很多人反映多線程很難學習,很複雜;另外一方面,新技術框架層出不窮,學習過程疲於奔命,效果和方向卻很茫然。

這是因為多數多線程的文章都偏重於技術框架API,而沒有說清楚整體框架和思路,沒有全局觀,本文偏重於全局概念和思路。

一,多線程問題只有兩種模式:多線程競爭和多線程協作。

線程只是一種表象,線程的本質是任務,協作和競爭的對象是數據。因此根本的問題是:任務和數據之間的關係。

多個任務和數據之間有兩種關係:競爭關係和協作關係。

任務有多種體現形式:進程,線程,協程……他們是不同重量級(資源鎖定/佔用)的任務實現方式。

進程是有CPU和內存佔用的任務;線程是佔用CPU但是沒有單獨內存資源的任務——在一些OS中,進程和線程是沒有區別的;協程是沒有用戶態和內核態切換的任務,是純粹的邏輯塊,是沒有任何IO消耗的純粹被事件驅動的邏輯塊。

在LINUX中,原生進程是可以通過管道進行通訊的,但是JAVA線程不可以。他們通訊的唯一方式就是數據和信號。

影響軟體性能的幾個瓶頸資源分別是

1,IO(既數據)2,線程依賴(即鎖:線程對線程的依賴——本質還是對數據的依賴)

這兩個因素會極大的影響(降低)系統的性能。全速的CPU邏輯運算速度是億級別,千萬級別的,涉及到IO和鎖,就降低為*W級別了。

高性能軟體必須考慮瓶頸資源的使用,必須滿足以下三個原則

1,讓瓶頸資源最大限度得到發揮2,不做無用的事情3,通過合理調度完成

二,在多線程競爭場景中,高性能的程序解決思路是無鎖和弱化鎖

盡量的無鎖,細粒度鎖,局部鎖,短促鎖……比如眾所周知的ShareNothing架構,短事務,JUC包,讀寫分離……等,是這種思路的產物。

三,在多線程協作場景中,涉及到信號機制

1,線程鎖模型

常見的是CountDown,Semphore等包,這其實是一種效率稍低的信號機制,因為它鎖定線程本身

有沒有無線程鎖定的信號機制呢?

2,Actor模型就是這種思路的產物

Actor模型下有Vertx,akka等。他的線程是用完即釋放的。極大的提升了線程資源的利用率,比線程鎖模型有更大的並發處理能力

還有沒有優化的空間呢?

有,12提升的是線程資源的利用率,還可以從IO上考慮

3,IO優化框架

Netty是一種IO線程框架,他的事件源是IO。它解決的問題是IO和線程速率不匹配下的資源利用率問題。

但是Netty弊病是依賴於IO,如果阻塞的事件源不是IO,那Netty提升不了效率

有沒有不依賴於IO的事件線程機制呢?

這就是Actor模型。

Actor模型相比於12模型,他本質上分離了IO和任務塊,他的任務調度依賴於純粹的事件機制,而不是IO事件。akka/Vertx/MQ都可以歸為此類(MQ消耗太高,傳統觀念上就不歸為此類,但原理一致的)

那麼這是否就是最高性能呢?

no,在操作系統層面,有可能一次任務切換回涉及到OS的用戶態和內核態切換,由於OS的安全機制,會做數據拷貝。這也是極大的性能消耗。

消除OS層麵線程上下文切換的消耗,這就是協程等框架的基本原理。

所以協程框架必須讓業務系統告訴(協程)框架:阻塞點是什麼,任務塊是什麼,這需要在邏輯書寫層面引入一些標記來區分,告訴框架應該如何去調度。

4,CPU指令層面的優化

123措施基本已經考慮到機制了麼?還沒有,disruptor等框架還考慮對CPU底層指令進行冗餘填充,以提升CPU層面的處理速度。

(disruptor的Ring結構是另外一個層面——鎖優化——的問題,這裡不贅述)

五,實際業務系統優化做法

但是,我們並不鼓勵在業務代碼中考慮性能優化問題。

理論上,軟體系統本質上是一個函數f,是純粹的邏輯塊。它的速度是千萬級的,是遠遠超過任何業務場景要求的。

導致軟體系統性能降低的原因是

1,架構設計層面讓IO和業務邏輯耦合2,讓業務邏輯程序員關注了太多依賴,而沒有做好合適的模型設計和框架設計3,引入了太多框架,中間件……這些所謂的高性能框架,他們無論性能多麼高,都不可能高過CPU內核速度的。他們提升的是業務的彈性擴展能力和可用性冗餘——這對於絕大多數公司99.99%都是鏡花水月——設計良好的單機系統可以支撐100-10000的並發處理能力,遠遠在絕大多數公司的需求之上。

但是另外一方面,絕大多數公司真正需要的是業務系統的業務快速響應,靈活擴展能力——罕有架構師去考慮這真正是業務公司需要的問題。而把精力 都關注到不需要的性能上了。

再重複一遍:我們並不鼓勵在業務系統中考慮性能優化問題。

多數的情況下,只要你不做無意義的是(參見高性能原則2)就好了。

同樣的哲學下,請記得分散式架構設計第一原則,多線程第一原則,性能優化第一原則

1,不要分散式你的系統

2,不要多線程

3,不要性能優化

優秀的架構歡迎懶人,討厭多事的人

推薦閱讀:

相關文章