多線程基本概念總結,面試必備

本頭條號會不定期分享程序員的面試經驗,以及程序員需要掌握的技術乾貨,喜歡就關注我吧~

在Java程序員面試中,我們經常會被面試官問到如下問題:

為什麼HashMap不是線程安全的?

為什麼ConcurrentHashMap是線程安全的?

怎麼樣算線程安全?

什麼是悲觀鎖和樂觀鎖?

死鎖是什麼意思?

什麼情況下會發生死鎖?

並行和併發的區別是什麼?

等等....

多線程基本概念總結,面試必備

今天的主要內容是Java多線程編程中的基本概念總結,看完今天的內容你應該就能回答上面的這些問題了。

同步(Synchronous)和異步(Asynchronous)

同步和異步通常用來形容一次方法調用。同步方法調用一旦開始,調用者必須等到方法調用返回後,才能繼續後續的行為。異步方法調用更像是一個消息傳遞,一旦開始,方法調用就會立即返回,調用者就可以繼續後續的操作。

併發(Concurrency)和並行(Parallelism)

併發偏重於多個任務交替執行,而多個任務之間有可能還是串行的。並行是真正意義上的“同時執行”。

臨界區(Critical Section)

臨界區用來表示一種公共資源或共享數據,可以被多個線程使用,但是每一次只能有一個線程使用它。一旦臨界區資源被佔用,其他線程要想使用這個資源必須等待。

阻塞(Blocking)和非阻塞(Non-Blocking)

阻塞和非阻塞通常用來形容多線程間的相互影響。一個線程是阻塞的,那麼在其他線程釋放資源之前,當前線程無法繼續執行,線程會被掛起。非阻塞與之相反,所有的線程都會不斷向前執行。

死鎖(Deadlock)、飢餓(Starvation)和活鎖(Livelock)

死鎖、飢餓和活鎖都屬於多線程的活躍性問題。

死鎖是指兩個或以上線程執行時,因爭奪資源而互相等待的現象,若無外力作用,它們都將無法推進下去。

飢餓是指一個或多個線程因為種種原因無法獲得所需資源,導致一直無法執行,如優先級太低。

活鎖是指線程之間沒有被阻塞,但由於某些條件沒有滿足,導致一直重複嘗試,失敗,嘗試,失敗,比如互相謙讓。活鎖有一定機率解開,而死鎖則無法自行解開。解決活鎖的辦法:在重試機制中引入隨機性。

悲觀鎖(Pessimistic Locking)和樂觀鎖(Optimistic Locking)

悲觀鎖是指不管是否發生多線程衝突,只要存在這種可能,就每次訪問都加鎖。即假設衝突一定會發生。

樂觀鎖則是通過標記值控制,每次操作前通過標記值判斷是否是最新內容,最新內容就可以操作,不是最新的就繼續循環判斷標記值,直到是最新內容。即假設衝突不會發生。

樂觀鎖的優點是不會發生死鎖,並且在適量衝突的情況下,效率更高。樂觀鎖的實現:CAS、MVCC(多版本併發控制)。

線程安全(Thread safe)和競態條件(Race Condition)

當多個線程訪問某個類時,不管運行時環境採用何種調度方式或者這些線程將如何交替執行,並且在主調代碼中不需要任何額外的同步或協調,這個類都能表現出正確的行為,那麼就稱這個類是線程安全的。[Java併發編程實戰]

在線程安全的定義中,最核心的概念就是正確性。在線程安全類中封裝了必要的同步機制,因此客戶端無需進一步採取同步措施。

競態條件(race condition):在併發編程中,由於不恰當的執行時序而出現不正確的結果的情況。

最常見的競態條件是“先檢查後執行”。要避免競態條件,就必須在某個線程修改該變量時,通過某種方式防止其他線程使用這個變量,從而確保其他線程只能在修改操作完成之前或之後讀取和修改狀態,而不是在修改狀態的過程中。

內置鎖(monitor)

每個Java對象都可以用作一個實現同步的鎖,這些鎖被稱為內置鎖或監視器。線程在進入同步代碼塊之前會自動獲得鎖,並且在退出同步代碼塊時自動釋放鎖,不論是通過正常的控制路徑退出還是通過從代碼塊中拋出異常退出。

Java內置鎖相當於一種互斥體(或互斥鎖),最多隻有一個線程能持有這種鎖。內置鎖是可重入的。

完。

相關推薦

推薦中...