深入理解synchronized 八锁现象

深入理解synchronized 八锁现象(2-7的第一个方法都延迟四秒)

同一对象

1.同一对象的两个线程,调用一个类的两个加锁方法

锁的对象是方法的调用者,这时因为只有一个调用者,所以输出结果按锁的方法从上到下执行

public class Test1 {
    public static void main(String[] args) {
        Phone p = new Phone();

        new Thread(()->{
            p.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class Phone{
    public synchronized void SendSms(){
        System.out.println("发短信");
    }
    public synchronized void call(){
        System.out.println("打电话");
    }
}

先输出发短信,再输出打电话


2.同一对象的两个线程,调用一个类的两个加锁方法,在第一个加锁方法上加上等待4秒

锁的对象是方法的调用者,这时因为只有一个调用者,所以输出结果按锁的方法从上到下执行

public class Test1 {
    public static void main(String[] args) {
        Phone p = new Phone();

        new Thread(()->{
            p.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class 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("打电话");
    }
}

4秒后输出 发短信 一秒后输出打电话

3.同一对象的两个线程,调用一个类一个加锁方法一个不加锁方法,其中加锁方法等待4秒

hello 方法没加锁 不受锁限制 因为发短信那个方法等待4秒,所以先运行hello

public class Test34 {
    public static void main(String[] args) {
        Phone2 p = new Phone2();

        new Thread(()->{
            p.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        new Thread(()->{
            p.hello();
        },"B").start();
    }
}

class Phone2{
    public synchronized void SendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    
    public void hello(){
        System.out.println("hello");
    }
}

先输出hello 四秒后输出发短信

5. 同一对象两个线程,调用一个类的两个加锁静态方法,第一个加锁方法等待四秒

static是类一加载就有的,这时锁的是一整个class,而方法因为锁,所以从上到下执行

public class Test56 {
    public static void main(String[] args) {
        Phone3 p3= new Phone3();

        new Thread(()->{
            p3.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class Phone3{
    public static synchronized void SendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public static synchronized void call(){
        System.out.println("打电话");
    }

}

四秒后输出发短信,如输出打电话

7.同一对象两个线程,调用一个类的一个加锁静态方法,第二个方法是普通加锁方法,第一个加锁方法等待四秒

这时两个方法锁的对象是不一样的,第一个锁的是class,第二个锁的方法,所以两个方法没联系,先输出执行快的即打电话

public class Test78 {
    public static void main(String[] args) {
        Phone4 p4= new Phone4();

        new Thread(()->{
            p4.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class Phone4{
    public static synchronized void SendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    //普通锁
    public synchronized void call(){
        System.out.println("打电话");
    }

}

两个对象

4.两个对象,各调用同一个类的两个加锁方法,其中第一个加锁方法等待四秒

这时候因为有两个对象,所以其实是两把锁,所以先输出打电话

public class Test34 {
    public static void main(String[] args) {
        Phone2 p1 = new Phone2();
        Phone2 p2 = new Phone2();

        new Thread(()->{
            p1.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class Phone2{
    public synchronized void SendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public synchronized void call(){
        System.out.println("打电话");
    }


}

先输出打电话 四秒后输出发短信

6. 两个对象,调用一个类的两个加锁静态方法,第一个加锁方法等待四秒

这其实是第四个方法的加深版
从第四个可以知道:
static是类一加载就有的,这时锁的是一整个class,而方法因为锁,所以从上到下执行
这时候等四秒先输出发短信

public class Test56 {
    public static void main(String[] args) {
        Phone3 p3= new Phone3();
        Phone3 p4= new Phone3();

        new Thread(()->{
            p3.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class Phone3{
    public static synchronized void SendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public static synchronized void call(){
        System.out.println("打电话");
    }

}

四秒后输出发短信,然后输出打电话

8. 两个对象,调用一个类的一个加锁静态方法,第二个方法是普通加锁方法,第一个加锁方法等待四秒

跟方法7类似
这时两个方法锁的对象是不一样的,第一个锁的是class,第二个锁的方法,所以两个方法没联系,不管你几个对象,都先输出执行快的即打电话

public class Test78 {
    public static void main(String[] args) {
        Phone4 p4= new Phone4();
        Phone4 p5= new Phone4();

        new Thread(()->{
            p4.SendSms();
        },"A").start();

        //捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

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

class Phone4{
    public static synchronized void SendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    //普通锁
    public synchronized void call(){
        System.out.println("打电话");
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Andrew0219

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值