面試題:
1. synchronized和volatile的差別
2. final,finally,finalize差別
1. synchronized和volatile的差別
1.1 JVM記憶體模型
JVM将記憶體組織分為主記憶體和工作記憶體兩部分。
-
主記憶體
主記憶體包括方法區和堆。所有變量都存在主記憶體中,對于所有線程都是共享的。
-
工作記憶體
每一個線程有一個工作記憶體,它包含兩部分,該線程的私有棧和對主存部分變量拷貝的寄存器(包括程式計數器PC和CPU工作的高速緩存區)。
多線程模型下,每個工作線程不能通路另一個工作線程中的變量,線程間變量傳遞是通過主線程來完成的。是以可能存在這種情況,線程1對變量a進行指派了,還沒來得及寫入記憶體中,線程2不知道線程1已修改變量a的值,繼續使用a原來的值,這樣就會出現問題。
1.2 volatile
volatile是java的關鍵字,使用volatile修飾的變量會強制将修改的值立即寫入主存,主存中的值更新會使工作線程中的副本值失效。
- 保證記憶體可見性:某個線程修改了volatitle修飾的變量值,其他線程能夠及時知道。
- 禁止指令重排序:當程式執行到volatitle修飾的變量的讀寫操作時,可以保證之前的語句已執行完,也能确定後面的邏輯還未執行
- 不保證原子性:volatitle不保證變量的任何操作都是原子性的,比如i++
1.3 synchronized
synchronized依賴于JVM,保證了同一時刻隻能有一個線程在作用對象的作用範圍内進行操作。
- 記憶體可見性:線程在加鎖時,先清空工作記憶體->在主存中拷貝最新變量副本到工作線程->執行完代碼->将更改後的共享變量刷到主存中->釋放互斥鎖
- 操作的原子性:因為synchronized保證了同一時間隻有一個線程對代碼塊進行操作,是以操作是原子性的。
- 有序性:第一條的特性決定,在多線程環境中,代碼執行是有序的。
1.4 volatile和synchronized的差別
- volatile不會加鎖,比synchronized更輕量級,不會阻塞線程
- volatile标記的變量不會被編譯器優化而synchronized可以(比如編譯器重排優化)
- volatile是變量修飾符,而synchronized可以修改方法、變量、代碼塊、
- volatile不保證原子性,synchronized可以保證原子性
- 他們都能保證記憶體可見性
2. final,finally,finalize差別
2.1 final
final是個修飾詞,可以修飾類,方法和屬性
-
修飾類
final修飾的類不能被繼承。
-
修飾方法
主要由兩個原因
- 防止被繼承,修改
- 早期java版本中性能優化
-
修飾屬性
使用final修飾的屬性,一旦初始化後就不能修改 ,可以了解該屬性隻能讀不能改。
2.2 finally
finally做為異常處理的一部分,隻能用在try/catch語句中,如果try語句被執行那麼finally語句也肯定被執行(除非把程序殺掉了等異常情況)。
2.3 finalize
finalize()方法是在Object裡定義的,在對象被回收時調用。一般情況下不需要手動去實作該方法。
如果非要調用,得調用其super方法。
2.4 final,finally,finalize差別
其實他們沒有半毛錢關系,隻是長得像