1. 程式人生 > >JAVA高併發——瞭解並行世界

JAVA高併發——瞭解並行世界

        最近不知道怎麼了,感覺什麼東西都需要畫畫圖,梳理梳理思路、寫寫,而且每每晚上坐到自己的位置上,開啟本書,開啟篇文章,開啟思維導圖,開啟onenote,再開啟音樂,然後就開始靜靜理解著,梳理著,畫圖著,編寫著……感覺心情也能平靜下來。netty原始碼還需要多花點時間理解理解,週末再進行;今天開始把Java高併發多執行緒的知識也回顧整理一吧。

       以前學習高併發多執行緒的過程,現在想想就是看知識點,怎麼實現程式碼,很少去想為什麼是這樣,為什麼會這樣?而接下來,我希望能夠通過思維導圖,能夠通過聯想,能夠通過關聯,不斷完善自己的知識網,使一些知識融入到自己的知識網中,達到牽一髮動全身的效果。好,下邊進入正題吧。

 

        一,高併發多執行緒的由來:

       摩爾定律 大家應該都聽說過,大致意思是:當價格不變時,積體電路上可容納的元器件的數目,約每隔18—24月便會增加一倍,效能也將提升一倍。但是摩爾定律並不是一種自然法則或者物理定律,隨著硬體技術的發展,一些高科技技術越來越難突破,摩爾定律在CPU的計算效能上可能慢慢失效。(一個人幹活,隨著幹活的技巧、經驗越來越豐富,這個人幹活的效率越來越高,但是當這個人已經達到效率沒法再有質的提高的時,怎麼辦?善假於物業,找人一塊幫著幹)。人類的智慧是無窮無盡的,當單核CPU的效能無法提高時,那就雙核、四核、多核……讓多個cpu一起幫著處理需求,這樣高併發多執行緒就來了。(以前是硬體研發人員不斷的提高自己要求自己,現在也督促著軟體開發人員不停的提高自己要求自己了)。

 

       二,高併發多執行緒的幾個概念:

       1,同步(Synchronous)和非同步(Asynchronous):方法呼叫一旦開始,呼叫者必須等到方法呼叫返回後,才能繼續後續行為的屬於同步;非同步更像一個訊息傳遞,一旦開始,方法就會立即返回,呼叫可以繼續後續的行為。聯想一下:TCP、UDP;打電話、發簡訊;RPC方法呼叫、MQ訊息提供者消費者;單執行緒、多執行緒……

       2,併發(Concurrency)和並行(Parallelism):並行偏重兩個或多個任務同時執行;併發偏重多個任務交替執行。都可以表示多個任務一起執行。單核CPU沒法並行,只能併發,多個執行緒的不同任務,CPU交替執行(由於CPU執行效率特別高),看起來像”同時“執行,其實只是交替一起執行而已。

       3,臨界區(Critical region):用來表示一種公共資源或者說是共享資料,可以被多個執行緒使用。例如:辦公室的印表機,大家都可以使用,但是同一時間只能為一個員工服務,不能及列印員工A的又列印員工B的,那樣應該就出問題了。我們臨界區資源也是,一次被一個執行緒佔用,其它執行緒只能排隊,不能同時多個執行緒對其進行處理。這也就是我們經常說的共享資源在多執行緒的情況下需要加鎖。

       4,阻塞(Blocking)和非阻塞(Non-Blocking):接著上邊你說,如果臨界區的資源被一個執行緒佔用了 ,另一個執行緒只能等待,就會掛起也就是阻塞。

       5,死鎖(Deadlock)、飢餓(Starvation)和活鎖(Livelock):死鎖:幾個例子,做一件需要兩個資源A、B,執行緒1拿到了A,執行緒2拿到了B,從而導致兩個執行緒一直在等著彼此,像死迴圈一樣,解不開;            飢餓:是指某一個或者多個執行緒因為種種原因無法獲得所需的資源,導致一直無法執行,比如它的執行緒優先順序可能太低,而高優先順序的執行緒不斷搶佔它需要的資源;          活鎖:是指執行緒1可以使用資源,但它很禮貌,讓其他執行緒先使用資源,執行緒2也可以使用資源,但它很紳士,也讓其他執行緒先使用資源。這樣你讓我,我讓你,最後兩個執行緒都無法使用資源。活鎖不會被阻塞,而是不停檢測一個永遠不可能為真的條件。除去程序本身持有的資源外,活鎖狀態的程序會持續耗費寶貴的CPU時間。

 

       三,併發級別:

       阻塞(Blocking)——》無飢餓(Starvation-Free)——》無障礙(Obstruction-Free)——》無鎖(Lock-Free)——》無等待(Wait-Free),併發級別依次變高。

 

       四,有關並行的兩個重要定律:

       加速比定義:加速比 = 優化前系統耗時/優化後系統耗時。序列系統並行化後的加速比的計算公式和理論上限的公式定律:Amdahl定律 :當CPU處理器數量趨於無窮時,加速比與系統的序列化率成反比;例如如果系統中有50%的程式碼序列執行,那麼系統的最大加速比為2;Gustafson定律 :如果序列化比例很小,並行化比例很大,那麼加速比就是處理器的個數。  兩者角度不同,一個從優化前執行時間、優化後執行時間,看cpu個數的影響,只有再有序列部分的情況下它是有上限的;二是從優化前執行時間、優化後執行總時間(並行的時間加起來),看cpu個數的影響,只要在序列部分足夠小的情況下,是一直有優化空間的。一個是有上限,一個是我們可以不斷提高的。

 

       五,JMM的關鍵技術點都是圍繞著多執行緒的原子性、可見性和有序性來建立的。

       1,原子性(Atomicity):是指一個操作是不可中斷的。即使是在多個執行緒一起執行的時候,一個操作一旦開始,就不會被其他執行緒干擾。

       2,可見性(Visibility):是指當一個執行緒修改了某一個共享變數的值,其他執行緒是否能夠立即知道這個修改。

       3,有序性(Ordering):jvm執行命令是由指令重排會打錯一些多執行緒指令的執行順序(指令重排可以保證序列語句一致,但是沒有義務保證多執行緒間的語義也一直。具體的回頭在JVM的總結中會詳細說到),這裡重點看下Happen-Before規則:

       a,程式順序原則:一個執行緒內保證語義的序列性;

       b,volatile規則:volatile變數的寫,先發生於讀,這保證了volatile變數的可見性;

       c,鎖規則:解鎖必然發生在隨後的加鎖前;

       d,傳遞性:A優先於B,B優先於C,那麼A必然優先於C;

       e,執行緒啟動規則:執行緒的start()方法優先於它的每一個動作;

       f,執行緒終止規則:執行緒的所有操作優先於執行緒的終結;

       g,執行緒中斷規則:對執行緒interrupt()方法的呼叫先行發生於被中斷執行緒的程式碼檢測到中斷時間的發生;

       h,物件終結規則:物件的建構函式執行、結束先於finalize()方法。

 

      好,這篇重要扯了扯閒篇,瞭解了一下高併發多執行緒下的一些概念名詞。希望結合實際聯想,構建並不斷完善自己的知識網。好,初入高併發多執行緒、接下來繼續……