【多線程】Java高併發基礎

一、摩爾定律的失效和多線程的發展
摩爾定律的思想是,預計18個月會將芯片的性能提高一倍。但是在2004年,Intel CEO宣佈Intel徹底取消4G Hz計劃,至此摩爾定律在芯片上的發展已經失效了。如果計算機沒有辦法繼續提高單個CPU的性能,那麼就在一個CPU裏面塞很多的核進去,因此多核CPU興起。
在單核時代,多線程就有很廣泛的應用,這時候多線程大多用於降低阻塞。多線程的作用不只是用作並行計算,還可以提高CPU的利用率。

二、線程的介紹
線程是進程裏面更細微的執行單元,而多線程是爲了使得多個線程並行的工作以完成多項任務,以提高系統的效率,線程是在同一時間需要完成多項任務的時候被實現。

線程的基本操作

  1. 線程剛剛新建出來,那它的狀態就是new的狀態,new狀態的線程其實並沒有開始工作,它只是一個靜態的實體
  2. 當調用實例的start方法之後,線程才真正的被啓動。線程被啓動之後狀態變成RUNNABLE狀態,表示線程可以執行了,一切準備就緒(但RUNNABLE狀態並不一定表示這個線程一定在CPU上執行,有沒有真正在執行,取決於物理CPU的調度)
  3. 如果一個線程它的所有工作都做完了,那麼自然它就會被終結掉,狀態就處於TERMINATED狀態,表示線程任務執行結束
  4. 有些時候線程在執行過程中不可避免要去申請某些鎖,比如要求申請某些對象的一個定時器,比如調用了synchronized方法,這個時候線程可能會被阻塞住
  5. 如果一個線程在執行過程中調用了wait,那麼這個進程就會變成等待狀態WAITING,進入等待狀態的線程它會等待另一些線程對它進行通知,它被通知之後就會從WAITING狀態變爲RUNNABLE狀態,繼續執行
  6. 等待狀態分爲兩種,一種是無限期的等待,一種是有限期的等待(TIMED.WAITING,比如我就等待10秒,如果過了十秒沒有線程通知,就把狀態由WAITING變爲RUNNABLE)

使用線程的好處

  1. 使用線程可以把佔據長時間的程序中的任務放到後臺去處理;
  2. 用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度;
  3. 程序的運行速度可能加快;
  4. 在一些等待的任務實現上如用戶輸入、文件讀寫和網絡收發數據等,線程就比較容易了。在這種情況下,我們可以釋放一些珍貴的資源如內存佔用等等。

守護線程:
守護線程是指在後臺默默運行的一些系統,爲整個系統的運行提供一些支撐服務,能幫助系統做一些後臺運維方面的事情,可能跟業務關係不是很大。
如果主線程main函數結束了,或者是main函數所開啓的一些非守護線程結束了,這個時候我們可以認爲這個Java程序已經沒有存在的必要了(因爲程序存在的目的就是執行非守護線程)。非守護線程會執行一些業務邏輯,而守護線程往往只是起到一些輔助作用

線程優先級:
線程是有優先級的,具有優先級高的線程更容易搶佔系統資源,更快的執行。

三、一些重要的概念
同步和異步
同步和異步是對方法調用而言的。同步調用的等着方法調用結束之後返回結果,方法執行多久就等待多久
異步調用是會立即得到一個返回結果,但並不表示調用完成了,而是在後臺啓用一個線程慢慢的去做事情,但不影響後續調用事件的繼續。

併發和並行
並行是兩個線程或進程同時執行。併發是指一會兒做這件事情 一會兒做另一件事情(它有一個調度的過程)
對於單個CPU而言不可能出現並行,它同一時間只能處理一個線程(進程);對於多個CPU而言就是可以實現並行的

臨界區
臨界區用來表示一種公共資源或者是共享數據,可被多個線程使用。
但每一次只能有一個線程使用它,因爲如果不加限制,很可能因爲多個線程進入臨界區,把數據改壞掉。所以臨界區每一次只能有一個進程進去。
如果一個線程進入臨界區,其他線程也想進入臨界區,則需要進入阻塞隊列進行等待。

阻塞和非阻塞
阻塞和非阻塞通常用來形容多線程間的相互影響。比如一個線程進入了臨界區,其他線程不能進入臨界區,需要在臨界區之外進行等待,導致線程掛起,這種情況就是阻塞。
阻塞的意思就是指這個線程在操作系統層面,被掛起。
如果佔用資源的線程一直不願意釋放資源,那麼其他所有阻塞在這個臨界區的線程都不能工作。
非阻塞線程是允許多個線程同時進入臨界區。只要保證不把數據改壞就可以了。

死鎖、飢餓和活鎖:
對於阻塞隊列來講,在臨界區就有可能發生死鎖的現象。死鎖是使程序卡死在那兒,沒辦法繼續往下走,沒辦法提供服務了
死鎖雖然不是一個好現象,但死鎖屬於一個靜態的問題,一旦出現死鎖,所有線程都卡死,CPU的佔用率也是0,不會佔用CPU。
與死鎖對應的是活鎖,活鎖的例子是電梯遇人,一個要進去,一個要出去,兩人一直相對左右左右的避讓,結果一直進不去。活鎖是一個動態的問題,它不像死鎖那樣一直不動,性能會受到非常嚴重的影響
有的線程優先級很高,有的線程優先級很低,在調度的時候會調度不到優先級很低的線程,一直一直持續下去會被餓死。
比如同時阻塞在一個臨界區上,結果操作系統只調度優先級高的線程,因爲優先級很低所以調度不到,就不能往下繼續執行。這樣下去就會被餓死,因爲分不到足夠的資源

併發級別:
阻塞:一個線程進入臨界區之後,其他線程必須在臨界區外進行等待
非阻塞:
無障礙:無障礙是一種最弱的非阻塞調度;自由出入臨界區,無競爭時有限步驟內完成操作;有競爭時回滾數據(寬進嚴出的策略)
無鎖:無鎖在無障礙的基礎上,加一個約束,就是 保證有一個線程可以勝出
無等待:首先要保證無鎖;要求所有進入臨界區的線程都能在有限步內完成;無飢餓。是併發的最高級別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章