8 鎖物件

HuDu發表於2020-08-20

如何判斷鎖的物件是誰!永遠知道什麼是鎖,鎖的到底是誰!
深刻理解鎖

第一組

/**
 * 8 鎖,就是關於鎖的8個問題
 * 1、標準情況下,兩個執行緒列印,發簡訊還是打電話:先列印發簡訊
 * 2、sendSms延遲4秒,兩個執行緒列印,發簡訊還是打電話:還是先列印發簡訊
 */
public class Test1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        //鎖的問題
        new Thread(()->{
            phone.sendSms();
        },"A").start();

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

        new Thread(()->{
            phone.call();
        },"B").start();
    }

}

class Phone {

    //synchronized 鎖的物件是方法的呼叫者
    //兩個方法是同一鎖,誰先拿到誰先執行

    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發簡訊");
    }

    public synchronized void call() {
        System.out.println("打電話");
    }
}

第二組

/**
 * 8 鎖,就是關於鎖的8個問題
 * 3、增加了一個普通方法後,先列印發簡訊還是hello:先列印普通方法
 * 4、兩個物件,兩個同步方法,先列印發簡訊還是打電話:先列印打電話
 */
public class Test2 {
    public static void main(String[] args) {
        //兩個物件,兩個呼叫者,兩把鎖
        Phone2 phone1 = new Phone2();
        Phone2 phone2 = new Phone2();

        //鎖的問題
        new Thread(()->{
            phone1.sendSms();
        },"A").start();

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

//        new Thread(()->{
//            phone2.hello();
//        },"B").start();
        new Thread(()->{
            phone2.call();
        },"B").start();
    }

}

class Phone2 {

    //synchronized 鎖的物件是方法的呼叫者

    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發簡訊");
    }

    public synchronized void call() {
        System.out.println("打電話");
    }

    //這裡沒有鎖,不是同步方法,不受鎖的影響
    public void hello() {
        System.out.println("hello");
    }
}

第三組

/**
 * 5、增加兩個靜態的同步方法,只有一個物件,先列印:發簡訊
 * 6、兩個物件,增加兩個靜態的同步方法,先列印:發簡訊 ,對比不是靜態方法的結果
 */

public class Test3 {
    public static void main(String[] args) {
        //兩個物件的Class類别範本只有一個,static,鎖的是Class
        Phone3 phone1 = new Phone3();
        Phone3 phone2 = new Phone3();

        //鎖的問題
        new Thread(()->{
            phone1.sendSms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}

// Phone3 唯一的一個Class物件
class Phone3 {

    //synchronized 鎖的物件是方法的呼叫者
    //static 靜態方法
    //類一載入就有了,鎖的是Class 模版

    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發簡訊");
    }

    public static synchronized void call() {
        System.out.println("打電話");
    }

    //這裡沒有鎖,不是同步方法,不受鎖的影響
    public void hello() {
        System.out.println("hello");
    }
}

第四組

/**
 * 7、1個靜態的同步方法,1個普通的同步方法,一個物件,先列印:打電話,四秒後發簡訊,因為是兩個鎖,一個是類Class模板的鎖,一個是物件的鎖
 * 8、1個靜態的同步方法,1個普通的同步方法,兩個物件,先列印:打電話,四秒後發簡訊,因為是兩個鎖
 */
public class Test4 {
    public static void main(String[] args) {
        //兩個物件的Class類别範本只有一個,static,鎖的是Class
        Phone4 phone1 = new Phone4();
        Phone4 phone2 = new Phone4();

        //鎖的問題
        new Thread(()->{
            phone1.sendSms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}

// Phone3 唯一的一個Class物件
class Phone4 {

    //靜態的同步方法 鎖的是Class類别範本
    //區分類物件和例項物件
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發簡訊");
    }

    //普通的同步方法 鎖的呼叫者
    public synchronized void call() {
        System.out.println("打電話");
    }

    //這裡沒有鎖,不是同步方法,不受鎖的影響
    public void hello() {
        System.out.println("hello");
    }
}

小結

new    this    具體的物件
static    Class    唯一的模板
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章