【JUC】Java并发编程从挖坑到入土全解(2)

目录

我们锁的到底是什么(8个案例)

案例1

案例2

案例3

案例4

案例5

案例6

案例7

案例8

总结


我们锁的到底是什么(8个案例)

有a、b两个线程,我们基于如下代码进行改造:

public static void main(String[] args) {
        Phone phoneA = new Phone();
        new Thread(() -> {
            phoneA.sendEmail();
        }, "a").start();

        try {
            TimeUnit.MICROSECONDS.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() ->
        {
            phoneA.sendSMS();
        }, "b").start();
    }
}

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

    public synchronized void sendSMS() {
        System.out.println("sendSMS");
    }
}

请依次判断下在如下8个案例下,是先打印“sendEmail”?还是先打印“sendSMS”?

案例1

2个方法都是普通同步方法,方法内无其他逻辑(如下图)

【JUC】Java并发编程从挖坑到入土全解(2)_第1张图片

结果:先打印“sendEmail”,再打印“sendSMS”

案例2

打印“sendEmail”的方法中,添加暂停3秒的

【JUC】Java并发编程从挖坑到入土全解(2)_第2张图片

结果:(延迟3秒后)先打印“sendEmail”,再打印“sendSMS”

案例3

添加1个普通方法(无synchronized)

【JUC】Java并发编程从挖坑到入土全解(2)_第3张图片

结果:先打印“hello”,(延迟3秒后)再打印“sendEmail”

案例4

有2个phone(两个线程使用不同的phone对象)

【JUC】Java并发编程从挖坑到入土全解(2)_第4张图片

结果:先打印“sendSMS”,(延迟3秒后)再打印“sendEmail”

案例5

2个方法都是静态同步方法,只有一个phone(两个线程使用同一个phone对象)

【JUC】Java并发编程从挖坑到入土全解(2)_第5张图片

结果:(延迟3秒后)先打印“sendEmail”,再打印“sendSMS”

案例6

2个方法都是静态同步方法,有2个phone(两个线程使用不同的phone对象)

【JUC】Java并发编程从挖坑到入土全解(2)_第6张图片

结果:(延迟3秒后)先打印“sendEmail”,再打印“sendSMS”

案例7

1个方法是静态同步方法,1个方法是普通同步方法,有1个phone(两个线程使用同一个phone对象)

【JUC】Java并发编程从挖坑到入土全解(2)_第7张图片

结果:先打印“sendSMS”,(延迟3秒后)再打印“sendEmail”

案例8

1个方法是静态同步方法,1个方法是普通同步方法,有2个phone(两个线程使用不同的phone对象)

【JUC】Java并发编程从挖坑到入土全解(2)_第8张图片

结果:先打印“sendSMS”,(延迟3秒后)再打印“sendEmail”

总结

  • 当对方法加synchronized关键字时,锁的是当前对象(this),所以即使是多线程只要调用的是同一个对象的synchronized方法,就需要串行执行(案例1和案例2),未被synchronized修饰的普通方法则不受影响(案例3)

  • 如果是不同对象则不受影响(案例4),分别在自己的对象上加锁,不会影响到别的对象

  • 当在带有“static”的方法上加了synchronized关键字时,锁的是当前类,无论几个对象,都要抢类的这一把锁,因而是否使用同一对象都会串行执行

  • 对于同步代码块呢,锁的是sychronized括号的对象

你可能感兴趣的:(JUC,Java,java,juc,并发,synchronized,锁)