8鎖現(xiàn)象

如何判斷鎖的是什么?

首先我們先來看下面的代碼。思考下面兩個(gè)問題。

/**
 * 1.Q:下面程序執(zhí)行后,是先打印 “看電影” 還是 “玩游戲” 呢? A:先打印“看電影”
 * 2.Q:若watchMovie方法延遲4秒,是先打印 “看電影” 還是 “玩游戲” 呢? A:先打印“看電影” */
public class Test01 {
    public static void main(String[] args){
        TV tv = new TV();
        new Thread(()->{
            tv.watchMovie();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            tv.playGame();
        },"B").start();
    }
}

class TV{

    public synchronized void watchMovie(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("看電影");
    }

    public synchronized void playGame(){
        System.out.println("打游戲");
    }
}

synchronized 鎖的對(duì)象是方法的調(diào)用者!
就上面代碼而言,看電影和玩游戲兩個(gè)方法是用的TV對(duì)象的一把鎖,所以誰先拿到誰先執(zhí)行!

我們?cè)谒伎枷旅鎯蓚€(gè)問題。

/**
 * 3.Q:增加了一個(gè)普通方法后,是先打印 “開機(jī)” 還是 “看電影” 呢? A:先打印“開機(jī)”
 * 4.Q:若兩個(gè)對(duì)象,兩個(gè)同步方法,是先打印 “看電影” 還是 “打游戲” 呢? A:先打印“打游戲” */
public class Test02 {
    public static void main(String[] args){
        TV2 tv1 = new TV2();
        TV2 tv2= new TV2();
        new Thread(()->{
            tv1.watchMovie();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            tv2.playGame();
        },"B").start();
    }
}

class TV2{

    public synchronized void watchMovie(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("看電影");
    }

    public synchronized void playGame(){
        System.out.println("打游戲");
    }

    public void open(){
        System.out.println("開機(jī)");
    }
}

就問題3而言,我們之前了解過synchronized 鎖的對(duì)象是方法的調(diào)用者!而普通方法沒有synchronized修飾,不受鎖控制,所以先執(zhí)行。
就問題4而言,兩個(gè)對(duì)象,就是兩個(gè)調(diào)用者,也就意味著有兩把鎖,所以要受時(shí)間延遲影響,先打印“打游戲”!

好的,那我們?cè)倏聪旅鎯山M問題:

/**
 * 5.Q:增加兩個(gè)靜態(tài)方法,只有一個(gè)對(duì)象,是先打印 “看電影” 還是 “玩游戲” 呢? A:先打印“看電影”
 * 6.Q:若兩個(gè)對(duì)象,兩個(gè)靜態(tài)方法,是先打印 “看電影” 還是 “玩游戲” 呢? A:先打印“看電影” */
public class Test03 {
    public static void main(String[] args){
        TV3 tv1 = new TV3();
        TV3 tv2 = new TV3();
        new Thread(()->{
            tv1.watchMovie();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            tv2.playGame();
        },"B").start();
    }
}

class TV3{

    public static synchronized void watchMovie(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("看電影");
    }

    public static synchronized void playGame(){
        System.out.println("打游戲");
    }
}

static 靜態(tài),全局唯一,static 方法在類加載的時(shí)候就存在了,synchronized 鎖static 方法本質(zhì)是鎖TV對(duì)象的Class模板,類的Class模板只有一個(gè),換而言之,調(diào)用者只有一個(gè),鎖只有一把,所以還是誰先拿到誰先執(zhí)行!

最后再來看下面兩個(gè)問題:

/**
 * 7.Q:增加1個(gè)靜態(tài) synchronized 方法,1個(gè)普通 synchronized 方法,只有一個(gè)對(duì)象,是先打印 “看電影” 還是 “打游戲” 呢? A:先打印“打游戲”
 * 8.Q:增加1個(gè)靜態(tài) synchronized 方法,1個(gè)普通 synchronized 方法,兩個(gè)對(duì)象,是先打印 “看電影” 還是 “打游戲” 呢? A:先打印“打游戲” */
public class Test04 {
    public static void main(String[] args){
        TV4 tv1 = new TV4();
        TV4 tv2 = new TV4();

        new Thread(()->{
            tv1.watchMovie();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            tv2.playGame();
        },"B").start();
    }
}

class TV4{

    public static synchronized void watchMovie(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("看電影");
    }

    public synchronized void playGame(){
        System.out.println("打游戲");
    }
}

就問題7而言,靜態(tài)synchronized方法和普通synchronized鎖的調(diào)用者不是一個(gè),前者是類的Class模板,后者是對(duì)象,所以有兩個(gè)調(diào)用者,也就存在兩把鎖,因此,時(shí)間延遲的原因占主導(dǎo)。同理問題8也是如此,兩個(gè)調(diào)用者兩把鎖!

總結(jié):關(guān)鍵理解鎖的對(duì)象是方法的調(diào)用者!鎖的對(duì)象無外乎兩種,一種是new的對(duì)象,而一種就是Class模板。要分清具體情況下究竟鎖的是什么?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容