1. 程式人生 > >Java同步關鍵字Synchronized深入理解

Java同步關鍵字Synchronized深入理解

題記

講講寫這篇部落格的原因,因為自認為對synchronized這個關鍵字很瞭解了,前幾天和一個剛好在找工作的朋友聊到了這個。結果他把面試遇到的一個問題給我出了出來,當我蒙圈的那一刻才懂得自己之前的瞭解只是皮毛。

正文

對於synchronized這個關鍵字,只要是學過java的我們對它都不陌生,而且感覺還非常熟悉。那我們就先來說一說面試和實際使用當中會遇到的兩個場景。

  • 場景1:
public class SynchronizedTest {
    public synchronized static int getGender(){
        return 1
; } public synchronized int getAge(){ return 25; } }

當同時呼叫這兩個方法的時候會不會阻塞?根據鎖的門栓的不同,靜態方法鎖的是類的位元組碼檔案,而例項方法鎖的是呼叫方法的例項物件。所以同時呼叫兩個方法並不會阻塞!

  • 場景2:
   public class SynchronizedTest {
    public synchronized int getGender() {
        return 1;
    }

    public synchronized int getAge
() { return 25; } public String getName() { return "測試"; } }

這種情況當同時呼叫三個方法的時候會不會阻塞,由場景1的經驗知道,前兩個鎖的物件是一樣的,所以前兩個方法之間會阻塞,第三個方法則不受影響。

  • 場景3:終極場景
public class SynchronizedTest {
    public synchronized int getGender() {
        return 1;
    }

    public int getAge() {
        int
i = 0; synchronized (this) { i++; return i; } } }

當同時呼叫這兩個方法的時候會不會阻塞?重點內容隨著查閱資料和對synchronized 的實現的深入瞭解,知道synchronized 修飾例項方法和修飾程式碼塊的synchronized(this)的內部實現是不一樣的,所以它們鎖的門栓並不是一樣的。修飾在例項方法上時它是基於常量池裡面的ACC_SYNCHRONIZED這個標識來實現的同步鎖機制,而修飾程式碼塊的這種synchronized(this)方式是基於物件儲存的時候的頭物件中的Mark Word裡面的資訊來實現的。
於2018-08-11特意來道歉,上面的描述不夠準確,經過自測,雖然synchronized修飾程式碼塊和修飾方法通過用javap -c 命令反編譯的彙編來看是不一樣的,但是他們還是獲得的一樣的鎖,一樣會互斥阻塞。反編譯參考下面文章
https://www.cnblogs.com/huangyin/p/6586469.html

感想

後續還要持續研究,繼續深入瞭解java相關的深入實現~
另外附上對此理解更深刻,研究比較透徹的幾篇文章