JUC高级多线程_03:关于多线程锁的八个常见问题

我是 ABin-阿斌:写一生代码,创一世佳话,筑一揽芳华。 如果小伙伴们觉得我的文章有点 feel ,那就点个赞再走哦。
在这里插入图片描述

1 . 多线程情况下关于锁会出现的八项问题:

代码演示:

public class JUC04_Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();

        //问题四:
        // 新增一个资源类
        Phone phone2 = new Phone();

        new Thread(()->{
            phone.sendMes();
//            phone.sendMes2();

            },"Thread_A").start();

        //问题一:
        // 加一个时间间隔,保证 A 先启动
        Thread.sleep(200);

        new Thread(()->{
//            phone.sendEmall();
//            phone.hello();
//            phone2.sendEmall();
//            phone.sendEmall2();

            //问题六:
            // 两个资源类
//            phone2.sendEmall2();

            //问题七:
            // 1 个普通方法,1 个静态方法, 1 个资源类
//            phone.sendEmall2();

            //问题八:
            // 1 个普通方法,1 个静态方法, 2 个资源类
            phone2.sendEmall2();

            },"Thread_B").start();

    }
}
class Phone{
    public synchronized void sendEmall(){
        System.out.println("-----发送邮件-----");
    }
    public synchronized void sendMes(){
        //问题二:
        // 让发送短信暂停 4 秒
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("++++++发送短信++++++");
    }

    //问题五:
    // 两个静态方法类
    public synchronized void sendEmall2(){
        System.out.println("--静态---发送邮件-----");
    }
    public synchronized void sendMes2(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("++静态++++发送短信++++++");
    }


    //问题三:
    // 新建一个 hello 方法
    public void hello(){
        System.out.println("hello");
    }
}

1. 问题一:正常访问,先打印短信还是邮件

  • 答案:短信

2. 问题二:停4秒在短信方法内,先打印短信还是邮件

  • 答案: 短信
  • 针对第一、二问题原理说明:
    • synchronized 锁的不是单个方法,而是该方法所在的整个资源类
    • 所以某一个时刻内,只要一个线程去调用其中的一个 synchronized 方法了,其它的线程都只能等待
    • 换句话说,某一个时刻内,只能有唯一一个线程去访问这些 synchronized 方法
    • 锁的是当前对象 this,被锁定后,其它的线程都不能进入到当前对象的其它的 synchronized 方法

3. 问题三:普通的hello方法,是先打短信还是hello

  • 答案: Hello
  • 针对第三个问题原理说明:
    • 普通方法和同步锁无关

4. 问题四:现在有两部手机,先打印短信还是邮件

  • 答案: 邮件
  • 针对第四个问题原理说明:
    • 换成两个对象后,不是同一把锁了,每个线程都有自己的资源类
    • 情况立刻变化,互不相干

5. 问题五:两个静态同步方法,1部手机,先打印短信还是邮件

  • 答案: 短信

6. 问题六:两个静态同步方法,2部手机,先打印短信还是邮件

  • 答案: 短信

7.问题七:1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件

  • 答案: 邮件

8. 问题八:1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件

  • 答案: 邮件
  • 针对第五、六、七、八这四个问题的原理说明:
    • 加上 static 后该方法就不是针对实例化的对象,而是针对整个类
    • 所以 加上 staticsynchronized 锁的不是具体的实例化对象,而是锁的整个 类
    • synchronized 实现同步的基础: Java 中的每一个对象都可以作为锁。
    • 具体表现为以下三种形式:
      • 对于普通同步方法,锁是当前实例对象。
      • 对于静态同步方法,锁是当前类的 Class 对象。
      • 对于同步方法块,锁是 Synchonized 括号里配置的对象

9. 总结:

注意事项:
  • 当一个线程试图访问同步代码块时,必须先得到锁,当退出或抛出异常时必须释放锁 。也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁。
  • 可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以不必要等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。
  • 所有的静态同步方法用的也是同一把锁:类对象本身
  • 这两把锁(this / class)是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。
  • 但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值