八個例子徹底理解鎖

例子一:一個對象,兩個加鎖方法
下面代碼運行結果是先輸出打電話還是發短信

public class Test1 {
    public static void main(String[] args) {
        Phone phone= new Phone();
         //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone.sendMessage();
        },"A").start();

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

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
  public  synchronized  void sendMessage(){
      System.out.println("發短信");
  }

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

例子二:在例子一的基礎上讓第一個加鎖方法睡眠4秒再執行
下面代碼運行結果是先輸出打電話還是發短信


public class Test1 {
    public static void main(String[] args) {
        Phone phone= new Phone();
         //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone.sendMessage();
        },"A").start();
        //捕獲
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
   //synchronized 鎖的對象是方法的調用者
   //兩個方法調用的是同個鎖即Phone,說先獲取到就誰先輸出
  public  synchronized  void sendMessage(){
      try {
      //睡眠4秒再執行
          TimeUnit.SECONDS.sleep(4);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      System.out.println("發短信");
  }
 //synchronized 鎖的對象是方法的調用者
  public  synchronized  void call(){
      System.out.println("打電話");
  }
}

例子三:一個普通方法hello和一個加鎖的方法
下面代碼運行結果是先輸出你好還是發短信


public class Test2 {
    public static void main(String[] args) {
        Phone2 phone= new Phone2();
        //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone.sendMessage();
        },"A").start();

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

        new Thread(()->{
            phone.hello();
        },"B").start();
    }
}
class Phone2{
    
    public  synchronized  void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發短信");
    }

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

例子四:兩個對象,兩個加鎖方法
下面代碼運行結果是先輸出打電話還是發短信

//兩個對象,兩個同步方法,先打電話後發短信
public class Test2 {
    public static void main(String[] args) {
        //兩個對象
        Phone2 phone1= new Phone2();
        Phone2 phone2= new Phone2();
        //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone1.sendMessage();
        },"A").start();

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

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

    public  synchronized  void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發短信");
    }

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

 
}

例子五:一個對象,兩個static加鎖方法
下面代碼運行結果是先輸出打電話還是發短信


public class Test3 {
    public static void main(String[] args) {
        Phone3 phone= new Phone3();
        //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone.sendMessage();
        },"A").start();

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

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone3{
   //static靜態方法
    //類一加載就有了 鎖的class類
    //所以此時鎖的是同一個鎖
    public static synchronized  void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發短信");
    }

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


}

例子六:兩個對象,兩個static加鎖方法
下面代碼運行結果是先輸出打電話還是發短信


public class Test3 {
    public static void main(String[] args) {
        //兩個對象的class類模板只有一個,static鎖的是class
        Phone3 phone1= new Phone3();
        Phone3 phone2= new Phone3();
        //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone1.sendMessage();
        },"A").start();

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

        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
class Phone3{
   //static靜態方法
    //類一加載就有了 鎖的class類
    //所以此時鎖的是同一個鎖
    public static synchronized  void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發短信");
    }

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

例子七:一個對象,一個static加鎖方法,一個普通加鎖同步方法
下面代碼運行結果是先輸出打電話還是發短信


public class Test4 {
    public static void main(String[] args) {
        Phone4 phone= new Phone4();
        //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone.sendMessage();
        },"A").start();

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

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone4{
    //靜態同步方法,鎖的類模板
    public static synchronized  void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發短信");
    }

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


}

例子八:兩個對象,一個static加鎖方法,一個普通加鎖同步方法
下面代碼運行結果是先輸出打電話還是發短信


public class Test4 {
    public static void main(String[] args) {

        Phone4 phone1= new Phone4();
        Phone4 phone2= new Phone4();
        //這裏的->是lambda表達式的寫法
        new Thread(()-> {
            phone1.sendMessage();
        },"A").start();

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

        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
class Phone4{
    //靜態同步方法,鎖的類模板
    public static synchronized  void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("發短信");
    }

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


}

例子一運行結果:發短信 打電話
例子二運行結果:等待4秒後輸出 發短信 打電話
例子三運行結果:先輸出你好 後輸出 發短信
例子四運行結果:先輸出打電話 再發短信
例子五運行結果:先發短信後打電話
例子六運行結果:先發短信後打電話
例子七運行結果:先打電話,後發短信
例子八運行結果:先打電話,後發短信

小結

static synchronized 鎖的是class
synchronized 鎖的是對象
誰先獲取到對象誰就先執行

聲明:本文爲學習狂神說java的juc併發編程所做的筆記,狂神說javajuc併發編程地址:https://www.bilibili.com/video/BV1B7411L7tE?p=11

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章