并发编程中Synchronized锁的七个问题 带你了解锁的究竟是谁

锁能锁的东西只有两个,一个是new出来的对象, 另一个是Class模板,因为对象是由Class模板new出来的所以class模板也可以上锁
对象可以有多个,但class模板只有一个

1.执行下面这段代码,那个方法会先执行?

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public  synchronized  void  eat(){
        System.out.println("猫在吃东西");

    }
    public  synchronized  void  sleep(){
        System.out.println("猫在睡觉");
    }

	//主方法
    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest cat = new  SynchronizedTest();
        //启动线程执行cat类的方法
        new Thread(()->{
            //执行方法
            cat.eat();
        },"A").start();
		//执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            cat.sleep();
        },"B").start();
    }
}


答:Synchronized锁的是方法的调用者也就是 cat这个实例。因为这两个线程调用的是同一个实例的方法,所以谁先调用谁就获得锁。
在这里插入图片描述
2.在线程中加入睡眠,输出的结果又是怎样

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public  synchronized  void  eat(){
        System.out.println("猫在吃东西");

    }
    public  synchronized  void  sleep(){
        System.out.println("猫在睡觉");
    }


    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest cat = new  SynchronizedTest();
        //启动线程执行cat类的方法
        new Thread(()->{
            //睡眠
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //执行方法
            cat.eat();
        },"A").start();
        //执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            cat.sleep();
        },"B").start();
    }
}


答: 因为线程中睡眠的时间 超过了主线程中的睡眠时间,导致线程B中的sleep()方法首先获得了锁。在这里插入图片描述
3.在eat()方法中加入睡眠,输出的结果又是怎样

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public  synchronized  void  eat(){
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("猫在吃东西");

    }
    public  synchronized  void  sleep(){
        System.out.println("猫在睡觉");
    }


    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest cat = new  SynchronizedTest();
        //启动线程执行cat类的方法
        new Thread(()->{
            //执行方法
            cat.eat();
        },"A").start();
         //执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            cat.sleep();
        },"B").start();
    }

}

答:虽然eat()方法中有睡眠 但还是eat()方法先获得了锁,只有等eat()方法执行完 另一个方法才能获取到锁
在这里插入图片描述

4.把sleep()方法改成普通类,不再用synchronized修饰,结果会怎样

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public  synchronized  void  eat(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("猫在吃东西");

    }
    public   void  sleep(){
        System.out.println("猫在睡觉");
    }


    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest cat = new  SynchronizedTest();
        //启动线程执行cat类的方法
        new Thread(()->{
            //执行方法
            cat.eat();
        },"A").start();
        //执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            cat.sleep();
        },"B").start();
    }

}

答:因为sleep()方法是普通类没有锁,不受锁的影响,那么这两个线程之间没有关系,各自运行。但因为eat()方法中有睡眠,且大于主线程中的睡眠时间,所以线程B中的内容会先输出来
在这里插入图片描述
5.实例化两个类,两个同步方法,结果又如何?

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public  synchronized  void  eat(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("猫在吃东西");

    }
    public  synchronized  void  sleep(){
        System.out.println("猫在睡觉");
    }


    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest cat = new  SynchronizedTest();
        SynchronizedTest cat2 = new  SynchronizedTest();
        //启动线程执行cat类的方法
        new Thread(()->{
            //执行方法
            cat.eat();
        },"A").start();
        //执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            cat2.sleep();
        },"B").start();
    }
}

答:因为是两个实例化的对象,锁的是各自的对象,也就是有两把锁,两个线程之间没有联系,因为A线程中eat()方法中的睡眠时间大于主线程中的睡眠时间,所以B线程中的内容会先输出出来
在这里插入图片描述
6.把两个方法变成静态方法,那结果又该如何

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public static synchronized  void  eat(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("猫在吃东西");

    }
    public static synchronized  void  sleep(){
        System.out.println("猫在睡觉");
    }


    public static void main(String[] args) throws InterruptedException {
        //启动线程执行cat类的方法
        new Thread(()->{
            //执行方法
            SynchronizedTest.eat();
        },"A").start();
        //执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            SynchronizedTest.sleep();
        },"B").start();
    }



}

回答:静态方法在类加载的时候就已经生成了,所以synchronized锁的不再是对象 而是Class模板,因为Class模板只有一个所以这两个方法用的是同一个锁,所以谁先获取到锁就先执行谁。
在这里插入图片描述
7.一个设置成静态方法,一个同步方法,结果如何

import java.util.concurrent.TimeUnit;

/**
 * @Author : chenjianbo
 * @Data : 2022/1/19 16:14
 */
public class SynchronizedTest {
    public static synchronized  void  eat(){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("猫在吃东西");

    }
    public  synchronized  void  sleep(){
        System.out.println("猫在睡觉");
    }


    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest cat = new  SynchronizedTest();

        //启动线程执行cat类的方法
        new Thread(()->{
            //执行方法
            SynchronizedTest.eat();
        },"A").start();
        //执行完A线程以后 主线程睡眠几秒后在执行B线程
        TimeUnit.SECONDS.sleep(2);
        //启动线程执行cat类的方法
        new Thread(()->{
            cat.sleep();
        },"B").start();
    }



}

答:static synchronized 锁的是对象,synchronized 锁的是Class模板,两者锁的东西不一样即有两个锁,两个线程之间没有关系,虽然A线程中的方法有睡眠 但睡眠时间短于主线程睡眠的时间,所以A线程的内容会先输出出来。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

辰溪0502

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

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

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

打赏作者

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

抵扣说明:

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

余额充值