10.JUC線程高級(jí)-線程八鎖

所謂線程八鎖實(shí)際上對(duì)應(yīng)于是否加上synchronized,是否加上static等8種常見情況,代碼如下:

1.兩個(gè)普通同步方法,兩個(gè)線程,標(biāo)準(zhǔn)打印,結(jié)果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getTwo();
            }
        }).start();
    }
}
class Number{
    public synchronized void getOne(){
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

2.新增Thread.sleep()給getOne(),結(jié)果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getTwo();
            }
        }).start();
    }
}
class Number{
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

3.新增普通方法getThree(),結(jié)果:three one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getTwo();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getThree();
            }
        }).start();
    }
}
class Number{
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
    public void getThree(){
        System.out.println("Three");
    }
}

4.兩個(gè)普通同步方法,兩個(gè)對(duì)象,結(jié)果:two one

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

5.修改getOne()為靜態(tài)同步方法,結(jié)果:two one

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

6.修改兩個(gè)方法均為靜態(tài)同步方法,一個(gè)對(duì)象,結(jié)果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public static synchronized void getTwo(){
        System.out.println("Two");
    }
}

7.一個(gè)靜態(tài)同步方法,一個(gè)非靜態(tài)同步方法,兩個(gè)對(duì)象,結(jié)果:two one

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public  synchronized void getTwo(){
        System.out.println("Two");
    }
}

8.兩個(gè)靜態(tài)同步方法,兩個(gè)對(duì)象,結(jié)果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public static synchronized void getTwo(){
        System.out.println("Two");
    }
}

以上就是線程的八種常見的情況,線程八鎖的關(guān)鍵在于:

非靜態(tài)方法的鎖默認(rèn)為this,靜態(tài)方法的鎖為對(duì)應(yīng)的class實(shí)例(這里是Number.class)
某一個(gè)時(shí)刻內(nèi),只能有一個(gè)線程持有鎖,無論有幾個(gè)方法。

總結(jié):

①一個(gè)對(duì)象里面如果有多個(gè)synchronized方法,某一個(gè)時(shí)刻內(nèi),只要一個(gè)線程去調(diào)用其中的一個(gè)synchronized方法了,其他的線程都只能等待,換句話說,某一時(shí)刻內(nèi),只能有唯一一個(gè)線程去訪問這些synchronized方法。

②鎖的是當(dāng)前對(duì)象this,被鎖定后,其他線程都不能進(jìn)入到當(dāng)前對(duì)象的其他的synchronized方法。

③加個(gè)普通方法后發(fā)現(xiàn)和同步鎖無關(guān)。

④換成靜態(tài)同步方法后,情況又變化

⑤所有的非靜態(tài)同步方法用的都是同一把鎖 -- 實(shí)例對(duì)象本身,也就是說如果一個(gè)實(shí)例對(duì)象的非靜態(tài)同步方法獲取鎖后,該實(shí)例對(duì)象的其他非靜態(tài)同步方法必須等待獲取鎖的方法釋放鎖后才能獲取鎖,可是別的實(shí)例對(duì)象的非靜態(tài)同步方法因?yàn)楦搶?shí)例對(duì)象的非靜態(tài)同步方法用的是不同的鎖,所以毋須等待該實(shí)例對(duì)象已經(jīng)取鎖的非靜態(tài)同步方法釋放鎖就可以獲取他們自己的鎖。

⑥所有的靜態(tài)同步方法用的也是同一把鎖 -- 類對(duì)象本身,這兩把鎖是兩個(gè)不同的對(duì)象,所以靜態(tài)同步方法與非靜態(tài)同步方法之間不會(huì)有競(jìng)爭(zhēng)條件。但是一旦一個(gè)靜態(tài)同步方法獲取鎖后,其他的靜態(tài)同步方法都必須等待該方法釋放鎖后才能獲取鎖,而不管是同一個(gè)實(shí)例對(duì)象的靜態(tài)同步方法之間,還是不同的實(shí)例對(duì)象的靜態(tài)同步方法之間,只要它們是同一個(gè)實(shí)例對(duì)象

?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • JUC 原創(chuàng)者:文思,感謝尚硅谷,資料來源于尚硅谷 目錄: 1、volatile關(guān)鍵字與內(nèi)存可見性 2、原子變量與...
    文思li閱讀 2,538評(píng)論 0 1
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書筆記,整理的知識(shí)點(diǎn),也是為了防止忘記,尊重勞動(dòng)成果,轉(zhuǎn)載注明出處哦!如果你也喜歡,那...
    波波波先森閱讀 11,639評(píng)論 4 56
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,908評(píng)論 0 11
  • 上大學(xué)的時(shí)候,特別喜歡憧憬。 我有個(gè)大學(xué)同學(xué),長(zhǎng)的特高,至少我一直認(rèn)為他很高。到底有多高?1米90的身高,至少pk...
    3ea9f9044097閱讀 465評(píng)論 0 0
  • 主人公Gardener原本有一個(gè)幸福的家庭,由于投資失利,逐漸讓家庭經(jīng)濟(jì)陷入困境。妻子在絕望之下最終也離開了他。 ...
    77b9dc450adc閱讀 278評(píng)論 0 2

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