2022.8.21 8锁的现象

5、8锁的现象

如何判断锁的是谁,锁到底锁的是谁:对象和class

Test1

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 8锁,就是关于锁的八个问题
  * 1.标准情况下,两个线程去打印 先输出发短息还是打电话?   输出结果 1、发短信 2、打电话
  * 1.sendSms延迟四秒,四个线先打印 先输出发短信还是打电话 输出结果 1、发短信 2、打电话
  */
 public class Test1 {
     public static void main(String[] args) throws InterruptedException {
         Phone phone = new Phone();
 ​
         new Thread(()->{
             phone.sendSms();
        },"A").start();
 ​
         //休息一秒
         TimeUnit.SECONDS.sleep(1);
 ​
 ​
         new Thread(() -> {
             phone.call();
        }, "B").start();
    }
 }
 ​
 class Phone {
      //synchronized 锁的对象是方法的调用者! 所以两个方法用的是phone的锁,每个对象只有一把锁,谁先拿到谁执行
     public synchronized void sendSms() {
   /*     try {
             TimeUnit.SECONDS.sleep(4);
         } catch (Exception e) {
             e.printStackTrace();
         }*/
         System.out.println("发信息");
    }
 ​
     public synchronized void call() {
         System.out.println("打电话");
    }
 }
 ​
 ​

Test2

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 增加了一个普通方法并且把call换成普通方法(Hello) 先输出发短信还是hello 输出结果 1、hello 2、发短信   因为hello()是一个普通方法
  */
 public class Test2{
     public static void main(String[] args) throws InterruptedException {
         Phone2 phone = new Phone2();
         new Thread(()->{
             phone.sendSms();
        },"A").start();
 ​
         TimeUnit.SECONDS.sleep(1);
 ​
         new Thread(() -> {
             phone.Hello();
        }, "B").start();
    }
 }
 ​
 class Phone2 {
      //synchronized 锁的对象是方法的调用者!
     public synchronized void sendSms() {
         try {
             TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
             e.printStackTrace();
        }
         System.out.println("发信息");
    }
 ​
     public synchronized void call() {
         System.out.println("打电话");
    }
 ​
     // 这里没有锁 不是同步方法 不受锁的影响
     public void Hello() {
         System.out.println("hello");
    }
 }
 ​

Test3

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 两个对象,两个同步方法, 先输出发短信还是打电话 输出结果 1、打电话 2、发短信
  * sendSms 睡了3秒 所以先输出打电话
  *
  */
 public class Test3{
     public static void main(String[] args) throws InterruptedException {
         //两个不同的对象,两个调用者,两把锁
         Phone3 phone1 = new Phone3();
         Phone3 phone2 = new Phone3();
         new Thread(()->{
             phone1.sendSms();
        },"A").start();
 ​
         TimeUnit.SECONDS.sleep(1);
 ​
         new Thread(() -> {
             phone2.call();
        }, "B").start();
    }
 }
 ​
 class Phone3 {
      //synchronized 锁的对象是方法的调用者!
     public synchronized void sendSms() {
         try {
             TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
             e.printStackTrace();
        }
         System.out.println("发信息");
    }
 ​
     public synchronized void call() {
         System.out.println("打电话");
    }
     
 }
 ​

Test4

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 增加两个静态的同步方法,只有一个对象,输出结果 1.发信息 2.打电话
  */
 public class Test4 {
     public static void main(String[] args) throws InterruptedException {
         Phone4 phone = new Phone4();
         new Thread(()->{
             phone.sendSms();
        },"A").start();
 ​
         TimeUnit.SECONDS.sleep(1);
 ​
         new Thread(() -> {
             phone.call();
        }, "B").start();
    }
 }
 // Phone4只有唯一的class对象         Class<Phone4> class = Phone4.class;
 ​
 class Phone4 {
     //加上static静态方法 : 类一加载就有了,所以锁得是整个Class 两个方法用的同一把锁
     public static synchronized void sendSms() {
         try {
             TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
             e.printStackTrace();
        }
         System.out.println("发信息");
    }
     public static synchronized void call() {
         System.out.println("打电话");
    }
 }
 ​

Test5

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 增加两个静态的同步方法,只有两个对象,输出结果 1.发信息 2.打电话 原因:static 锁的是整个Class
  */
 public class Test5 {
     public static void main(String[] args) throws InterruptedException {
         // 两个对象的Class对象模板只有一个 锁的是Class
         Phone5 phone1 = new Phone5();
         Phone5 phone2 = new Phone5();
         new Thread(()->{
             phone1.sendSms();
        },"A").start();
 ​
         TimeUnit.SECONDS.sleep(1);
 ​
         new Thread(() -> {
             phone2.call();
        }, "B").start();
    }
 }
 ​
 class Phone5 {
     
     public static synchronized void sendSms() {
         try {
             TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
             e.printStackTrace();
        }
         System.out.println("发信息");
    }
     public static synchronized void call() {
         System.out.println("打电话");
    }
 }
 ​

Test6

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 1个静态的同步方法和一个普通的同步方法,一个对象 ,输出结果 1.打电话 ,发短信
  */
 public class Test6 {
     public static void main(String[] args) throws InterruptedException {
         Phone6 phone = new Phone6();
         new Thread(()->{
             phone.sendSms();
        },"A").start();
 ​
         TimeUnit.SECONDS.sleep(1);
 ​
         new Thread(() -> {
             phone.call();
        }, "B").start();
    }
 }
 ​
 class Phone6 {
     // 静态同步方法 锁的是Class
     public static synchronized void sendSms() {
         try {
             TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
             e.printStackTrace();
        }
         System.out.println("发信息");
    }
 ​
     // 普通同步方法   锁的是对象phone     不需要等待sendSms(),因为两个方法用的不是用一把锁 sendSms()睡了3秒
     public synchronized void call() {
         System.out.println("打电话");
    }
 }
 ​

Test7

 package com.xing.lock8;
 ​
 import java.util.concurrent.TimeUnit;
 ​
 /**
  * 1个静态的同步方法和一个普通的同步方法,两个对象 ,输出结果 1.打电话 ,发短信
  */
 public class Test7 {
     public static void main(String[] args) throws InterruptedException {
         //两个对象的Class类模板只有一个
         Phone7 phone1 = new Phone7();
         Phone7 phone2 = new Phone7();
         new Thread(()->{
             phone1.sendSms();
        },"A").start();
 ​
         TimeUnit.SECONDS.sleep(1);
 ​
         new Thread(() -> {
             phone2.call();
        }, "B").start();
    }
 }
 ​
 class Phone7 {
     // 静态同步方法 锁的是Class
     public static synchronized void sendSms() {
         try {
             TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
             e.printStackTrace();
        }
         System.out.println("发信息");
    }
 ​
     // 普通同步方法   锁的是对象phone 因为两个方法用的不是用一把锁 sendSms()睡了3秒
     public synchronized void call() {
         System.out.println("打电话");
    }
 }
 ​

全面总结:

  • 普通带锁方法:锁对象,同一对象下的才按顺序执行,如果是同一个类下的不同对象则不受影响。

  • 普通不带锁方法:不受任何影响。

  • 静态带锁方法:锁类,同一个类下的所有对象的所有带锁方法都得按顺序执行。

  • 小结:

    • new this 具体的一个对象

    • static Class 唯一的模板

posted @ 2022-08-21 21:26  暴躁C语言  阅读(15)  评论(0编辑  收藏  举报