八锁现象

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 本身!

posted @ 2020-08-05 11:06  大酷仔  阅读(203)  评论(0编辑  收藏  举报