1 synchronized 關鍵字
- 使用 synchronized 關鍵字修飾的方法爲同步方法,由於 java 的每個對象都有一個內置鎖,當此關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處於阻塞狀態。( synchronized 關鍵字也可以修飾靜態方法,此時如果調用該靜態方法,將會鎖住整個類)
- 有 synchronized 關鍵字修飾的語句塊被稱爲同步代碼塊,被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步。
2 什麼是可重入鎖?
可重入鎖表示鎖具有可重入性,例如 synchronized,ReentrantLock 都是可重入鎖。可重入性表明了鎖的分配機制:基於線程的分配,而不是基於方法調用的分配。舉個簡單的例子,當一個線程執行到某個 synchronized 方法時,比如說 method1,而在 method1 中會調用另外一個 synchronized 方法 method2,此時線程不必重新去申請鎖,而是可以直接執行方法 method2。
class MyClass {
public synchronized void method1() {
method2();
}
public synchronized void method2() {
}
}
method1 和 method2 都用 synchronized 修飾了,假如某一時刻,線程A執行到了 method1,此時線程A獲取了這個對象的鎖,而由於 method2 也是 synchronized 方法,假如 synchronized 不具備可重入性,此時線程A需要重新申請鎖。但是這就會造成一個問題,因爲線程A已經持有了該對象的鎖,而又在申請獲取該對象的鎖,這樣就會線程A一直等待永遠不會獲取到的鎖。
而由於 synchronized 和 Lock 都具備可重入性,所以不會發生上述現象。
3 什麼是可中斷鎖?
可中斷鎖即可以相應中斷的鎖。Lock 是可中斷鎖,而 synchronized 不是可中斷鎖。如果某一線程A正在執行鎖中的代碼,另一線程B正在等待獲取該鎖,可能由於等待時間過長,線程B不想等待了,想先處理其他事情,我們可以讓它中斷自己或者在別的線程中中斷它,這種就是可中斷鎖。
4 什麼是公平鎖?
公平鎖即儘量以請求鎖的順序來獲取鎖。比如同時有多個線程在等待一個鎖,當這個鎖被釋放時,等待時間最久的線程(最先請求的線程)會獲得該鎖,這種就是公平鎖。非公平鎖無法保證鎖的獲取是否按照請求鎖的順序進行的,這樣就可能導致某個或者一些線程永遠獲取不到鎖。
synchronized 是非公平鎖,它無法保證等待的線程獲取鎖的順序。至於 ReentrantLock 和 ReentrantReadWriteLock,它默認情況下是非公平鎖,但是可以設置爲公平鎖。
5 synchronized 什麼情況下會釋放鎖?
- 獲取鎖的線程執行完了該代碼塊,然後線程釋放對鎖的佔有;
- 線程執行發生異常,此時 JVM 會讓線程自動釋放鎖。
- 調用 wait 方法,在等待的時候立即釋放鎖,方便其他的線程使用鎖.
6 Lock 和 synchronized 的區別?
- Lock 是一個接口,而 synchronized 是 Java 中的關鍵字,synchronized 是內置的語言實現
- synchronized 在發生異常時,會自動釋放線程佔有的鎖,因此不會導致死鎖現象發生;而 Lock 在發生異常時,如果沒有主動通過 unLock() 去釋放鎖,則很可能造成死鎖現象,因此使用 Lock 時需要在 finally 塊中釋放鎖
- Lock 可以讓等待鎖的線程響應中斷,而 synchronized 卻不行,使用 synchronized 時,等待的線程會一直等待下去,不能夠響應中斷
- 通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到
- Lock 可以提高多個線程進行讀操作的效率。在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當競爭資源非常激烈時(即有大量線程同時競爭),此時 Lock 的性能要遠遠優於 synchronized。所以說,在具體使用時要根據適當情況選擇
- Lock 可以設置等待鎖的時間,而 synchronized 不行
7 什麼是 CAS?
CAS(Compare And Swap) 無鎖算法: CAS 是樂觀鎖技術,當多個線程嘗試使用 CAS 同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試。CAS 有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改爲B,否則什麼都不做。
8 線程池的作用有哪些?
線程池的作用: 在程序啓動的時候就創建若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工作線程。線程池的作用如下:
- 降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗。
- 提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。
- 提高線程的可管理性。
9 什麼是線程安全以及解決機制?
線程安全是指在多線程環境中能永遠保證程序的正確性,其實,只有存在共享數據時才需要考慮線程安全問題。當一個類被多個線程進行訪問並且正確運行,它就是線程安全的。
如何解決?
- 加鎖:
a 鎖能使其保護的代碼以串行的形式來訪問,當給一個複合操作加鎖後,能使其成爲原子操作。一種錯誤的思想是隻要對寫數據的方法加鎖,其實這是錯的,對數據進行操作的所有方法都需加鎖,不管是讀還是寫
b 加鎖時需要考慮性能問題,不能總是一味地給整個方法加鎖 synchronized 就了事了,應該將方法中不影響共享狀態且執行時間比較長的代碼分離出去
c 加鎖的含義不僅僅侷限於互斥,還包括可見性。爲了確保所有線程都能看見最新值,讀操作和寫操作必須使用同樣的鎖對象
- 不共享狀態:
無狀態對象: 無狀態對象(沒有字段和引用)一定是線程安全的,因爲不會影響到其他線程
線程關閉: 僅在單線程環境下使用
- 不可變對象:
可以使用 final 修飾的對象保證線程安全,由於 final 修飾的引用型變量(除 String 外)不可變是指引用不可變,但其指向的對象是可變的,所以此類必須安全發佈,也即不能對外提供可以修改 final 對象的接口
10 死鎖
參考:什麼是死鎖?死鎖的預防?
11 關鍵字 volatile
12 synchronized 的實現原理
13 JVM 對 synchronized 的優化
14 Synchronized 與 Volatile 之間的區別
- Volatile 僅能使用在變量級別; Synchronized 則可以使用在變量、方法和同步代碼塊級別上。
- Volatile 僅能實現變量的修改可見性和有序性,並不能保證原子性;Synchronized 則可以保證變量的可見性、有序性、原子性。
- Volatile 不會造成線程的阻塞;Synchronized 可能會造成線程的阻塞。
- Volatile 標記的變量不會被編譯器優化; Synchronized 標記的變量可以被編譯器優化。
15 什麼是 Java 內存模型?
16 Java 併發包都有哪些?
參考:解釋一下鎖的一些基本概念:可重入鎖、可中斷鎖、公平鎖、讀寫鎖
synchronized和ReentrantLock有什麼區別
Java併發 - 什麼是線程安全(一).