JUC之锁的八种情况

准备工作

创建一个资源类Phone(手机), 里面两个方法sendEmail(发邮件), sendSMS(发短信), 都是线程同步方法

class Phone {
    public synchronized void sendSMS() {
        System.out.println("------sendSMS");
    }
    public synchronized void sendEmail() {
        System.out.println("------sendEmail");
    }
}

根据我们以下八种情况来进行调用

  1. 标准访问, 两个线程, 各自访问一个方法

    public class EightLocks {
        public static void main(String[] args) throws InterruptedException {
            Phone phone = new Phone();
            new Thread(()->{
                phone.sendSMS();
            }, "AA").start();
            Thread.sleep(100);
            new Thread(()->{
                phone.sendEmail();
            }, "BB").start();
        }
    }
    

    打印结果

    ------sendSMS
    ------sendEmail

  2. 在sendSMS方法中停留4秒, 其余与第一种情况一样

    public static synchronized void sendSMS() throws InterruptedException {
        //停留4秒
        TimeUnit.SECONDS.sleep(4);
        System.out.println("------sendSMS");
    }
    

    打印结果

    ------sendSMS
    ------sendEmail

    1-2情况说明:

    • 一个对象里面如果有多个synchronized方法, 某一个时刻内, 只要一个线程去调用其中的一个synchronized方法了, 其它的线程都只能等待, 换句话说,某一个时刻内, 只能有唯一的一个线程去访问这些synchronized方法
    • 锁的是当前对象this, 被锁定后, 其它的线程都不能进入到当前对象的其它的synchronized方法
  3. 新增普通方法hello(), 第一个线程调用sendSMS(), 第二个线程调用hello()

    //资源类中增加
    public void hello() {
        System.out.println("------getHello");
    }
    
    //主类中修改
    new Thread(()->{
        phone.hello();
    }, "BB").start();
    

    打印结果

    ------hello
    ------sendSMS

  4. 创建两个Phone实例, 一个调用sendSMS, 一个调用sendEmail

    public class EightLocks {
        public static void main(String[] args) throws InterruptedException {
            Phone phone1 = new Phone();
            Phone phone2 = new Phone();
            new Thread(()->{
                phone1.sendSMS();
            }, "AA").start();
            Thread.sleep(100);
            new Thread(()->{
                phone2.sendEmail();
            }, "BB").start();
        }
    }
    

    打印结果

    ------sendEmail

    ------sendSMS

    3-4情况说明:

    • 普通方法与锁无关, 不会被阻塞
    • 两个实例对象不是同一把锁
  5. 将sendSMS()和sendEmail()变成静态方法, 一个实例对象去调用

    class Phone {
        public static synchronized void sendSMS() {
            System.out.println("------sendSMS");
        }
        public static synchronized void sendEmail() {
            System.out.println("------sendEmail");
        }
    }
    
    public class EightLocks {
        public static void main(String[] args) throws InterruptedException {
            Phone phone = new Phone();
            new Thread(()->{
                phone.sendSMS();
            }, "AA").start();
            Thread.sleep(100);
            new Thread(()->{
                phone.sendEmail();
            }, "BB").start();
        }
    }
    

    打印结果

    ------sendSMS

    ------sendEmail

  6. 两个实例对象调用静态方法

    public class EightLocks {
        public static void main(String[] args) throws InterruptedException {
            Phone phone1 = new Phone();
            Phone phone2 = new Phone();
            new Thread(()->{
                phone1.sendSMS();
            }, "AA").start();
            Thread.sleep(100);
            new Thread(()->{
                phone2.sendEmail();
            }, "BB").start();
        }
    }
    

    打印结果

    ------sendSMS

    ------sendEmail

    5-6情况说明:

    • 对于普通方法来说, 锁的对象是this, 也就是当前实例对象
    • 对于静态方法来说, 锁的对象就是当前类的Class对象, 也就是说这个类的所有实例对象公用同一把锁
  7. 一个静态方法, 一个普通方法, 一个实例对象调用

    class Phone {
        public static synchronized void sendSMS() {
            System.out.println("------sendSMS");
        }
        public synchronized void sendEmail() {
            System.out.println("------sendEmail");
        }
    }
    
    public class EightLocks {
        public static void main(String[] args) throws InterruptedException {
            Phone phone = new Phone();
            new Thread(()->{
                phone.sendSMS();
            }, "AA").start();
            Thread.sleep(100);
            new Thread(()->{
                phone.sendEmail();
            }, "BB").start();
        }
    }
    

    打印结果

    ------sendEmail

    ------sendSMS

  8. 一个静态方法, 一个普通方法, 两个实例对象调用

    public class EightLocks {
        public static void main(String[] args) throws InterruptedException {
            Phone phone1 = new Phone();
            Phone phone2 = new Phone();
            new Thread(()->{
                phone1.sendSMS();
            }, "AA").start();
            Thread.sleep(100);
            new Thread(()->{
                phone2.sendEmail();
            }, "BB").start();
        }
    }
    

    打印结果

    ------sendEmail

    ------sendSMS

    7-8情况说明:

    • 不管是一个实例对象还是多个实例对象, 普通同步方法与静态同步方法的锁都不是同一把

我的个人主页: www.ayu.link
本文连接: ┏ (゜ω゜)=☞

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值