• 八锁现象


    1、标准访问,请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * **1、标准访问,请问先打印邮件1还是短信2?**
     * 
     * 
     */
    public class Test1 {
        public static void main(String[] args) {
            
            Phone phone = new Phone();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> {
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> {
                phone.sendMS();
            }, "B").start();
    
        }
    }
    
    // 手机,发短信,发邮件
    class Phone {
        // 被 synchronized 修饰的方法、锁的对象是方法的调用者、
        public synchronized void sendEmail() {
            System.out.println("sendEmail");
        }
    
        public synchronized void sendMS() {
            System.out.println("sendMS");
        }
    }
    

    2、邮件方法暂停4秒钟,请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * **2、邮件方法暂停4秒钟,请问先打印邮件还是短信?**
     */
    public class Test2 {
        public static void main(String[] args) {
    
            Phone2 phone = new Phone2();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> {
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> {
                phone.sendMS();
            }, "B").start();
    
        }
    }
    
    
    // 手机,发短信,发邮件
    class Phone2 {
        // 被 synchronized 修饰的方法、锁的对象是方法的调用者、
        public synchronized void sendEmail() {
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        public synchronized void sendMS() {
            System.out.println("sendMS");
        }
    }
    

    3、新增一个普通方法hello()没有同步,请问先打印邮件还是hello?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * 3、新增一个普通方法hello()没有同步,请问先打印邮件还是hello?
     */
    public class Test3 {
    
        // 回家  卧室(锁)   厕所
        public static void main(String[] args) {
    
            Phone3 phone = new Phone3();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> { // 一开始就执行了
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> { // 一秒后执行
                phone.hello();
            }, "B").start();
    
        }
    }
    
    // 锁:竞争机制
    
    // 手机,发短信,发邮件
    class Phone3 {
        // 被 synchronized 修饰的方法、锁的对象是方法的调用者、
        public synchronized void sendEmail() {
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        public synchronized void sendMS() {
            System.out.println("sendMS");
        }
    
        // 新增的方法没有被 synchronized 修饰,不是同步方法,所以不需要等待,其他线程用了一个把锁
        public void hello() {
            System.out.println("hello");
        }
    
    }
    

    4、两部手机、请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * **4、两部手机、请问先打印邮件还是短信?**
     */
    public class Test4 {
    
        // 回家  卧室(锁)   厕所
        public static void main(String[] args) {
            // 两个对象,互不干预
            Phone4 phone1 = new Phone4();
            Phone4 phone2 = new Phone4();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> { // 一开始就执行了
                phone1.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> { // 一秒后执行
                phone2.sendMS();
            }, "B").start();
    
        }
    
    }
    
    // 手机,发短信,发邮件
    class Phone4 {
        // 被 synchronized 修饰的方法、锁的对象是方法的调用者、调用者不同,没有关系,两个方法用得不是同一个锁!
        public synchronized void sendEmail() {
            // 善意的延迟
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        public synchronized void sendMS() {
            System.out.println("sendMS");
        }
    
    }
    

    5、两个静态同步方法,同一部手机,请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /*
     **5、两个静态同步方法,同一部手机,请问先打印邮件还是短信?**
     */
    public class Test5 {
        // 回家  卧室(锁)   厕所
        public static void main(String[] args) {
            // 两个对象,互不干预
            Phone5 phone = new Phone5();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> { // 一开始就执行了
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> { // 一秒后执行
                phone.sendMS();
            }, "B").start();
    
        }
    
    }
    
    
    // 手机,发短信,发邮件
    class Phone5 {
    
        // 对象    类模板可以new 多个对象!
        // Class   类模版,只有一个
    
        // 被 synchronized 修饰 和 static 修饰的方法,锁的对象是类的 class 对象!唯一的
        // 同一把锁
    
        public static synchronized void sendEmail() {
            // 善意的延迟
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        public static synchronized void sendMS() {
            System.out.println("sendMS");
        }
    
    }
    

    6、两个静态同步方法,2部手机,请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /** 第一次听可能不会,第二次也可能不会,但是不要放弃,你可以!
     **6、两个静态同步方法,2部手机,请问先打印邮件还是短信?**
     */
    public class Test6 {
    
        // 回家  卧室(锁)   厕所
        public static void main(String[] args) {
            // 两个对象,互不干预
            Phone5 phone = new Phone5();
            Phone5 phone2 = new Phone5();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> { // 一开始就执行了
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> { // 一秒后执行
                phone2.sendMS();
            }, "B").start();
    
        }
    
    }
    
    // 手机,发短信,发邮件
    class Phone6 {
    
        // 对象    类模板可以new 多个对象!
        // Class   类模版,只有一个
    
        // 被 synchronized 修饰 和 static 修饰的方法,锁的对象是类的 class 对象!唯一的
        // 同一把锁
    
        public static synchronized void sendEmail() {
            // 善意的延迟
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        public static synchronized void sendMS() {
            System.out.println("sendMS");
        }
    
    }
    

    7、一个普通同步方法,一个静态同步方法,同一部手机,请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * 7、一个普通同步方法,一个静态同步方法,同一部手机,请问先打印邮件还是短信?**
     */
    public class Test7 {
        // 回家  卧室(锁)   厕所
        public static void main(String[] args) {
            // 两个对象,互不干预
            Phone7 phone = new Phone7();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> { // 一开始就执行了
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> { // 一秒后执行
                phone.sendMS();
            }, "B").start();
    
        }
    }
    
    
    class Phone7{
        // CLASS
        public static synchronized void sendEmail() {
            // 善意的延迟
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        // 对象
        // 普通同步方法
        public synchronized void sendMS() {
            System.out.println("sendMS");
        }
    
    }
    

    8、一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信?

    package com.dakuzai.lock8;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * **8、一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信?**
     */
    public class Test8 {
    
        public static void main(String[] args) {
            // 两个对象,互不干预
            Phone8 phone = new Phone8();
            Phone8 phone2 = new Phone8();
    
            // 我们这里两个线程使用的是同一个对象。两个线程是一把锁!先调用的先执行!
            new Thread(() -> { // 一开始就执行了
                phone.sendEmail();
            }, "A").start();
    
            // 干扰
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> { // 一秒后执行
                phone2.sendMS();
            }, "B").start();
    
        }
    
    }
    
    
    
    class Phone8{
    
        // CLASS
        public static synchronized void sendEmail() {
            // 善意的延迟
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sendEmail");
        }
    
        // 对象
        // 普通同步方法
        public synchronized void sendMS() {
            System.out.println("sendMS");
        }
    
    }
    

    小结

    new this 本身的这个对象,调用者

    static class 类模板,保证唯一!

    • 一个对象中有多个 synchronized 方法,某个时刻内只要有一个线程去访问 synchronized 方法了就会被加锁,其他线程就会阻塞!

    • 加了一个普通方法后 ,两个对象,无关先后,一个有锁,一个没锁!情况会变化!

    • 换成静态同步方法,情况会变化! CLASS ,所有静态同步方法的锁唯一 对象实例class 本身!

  • 相关阅读:
    MySQL存储树形数据优化技笔记
    收集18个高大上的浏览器小技巧
    收集18个高大上的浏览器小技巧
    盘点15个不起眼但非常强大的 Vim 命令
    盘点15个不起眼但非常强大的 Vim 命令
    为什么开发者应该摒弃敏捷?(转)
    为什么开发者应该摒弃敏捷?(转)
    MySQL 中事务、事务隔离级别详解
    pandas数据对齐
    Bokeh绘图
  • 原文地址:https://www.cnblogs.com/dakuzai/p/13438588.html
Copyright © 2020-2023  润新知