synchronized八锁现象

51 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,[点击查看活动详情]

有如下对象MySource

class MyResource{

    public synchronized void sendEmail(){
        System.out.println("=======普通同步sendEmail");
    }

    public synchronized void playGame(){
        System.out.println("=======普通同步playGame");
    }

    public static synchronized void sendEmailStatic(){
        System.out.println("=======静态同步sendEmail");
    }

    public static synchronized void playGameStatic(){
        System.out.println("=======静态普通同步playGame");
    }

    public void helloWord(){
        System.out.println("=======普通方法helloWord");
    }

}
  1. 标准的两个线程先后访问同一个对象,是先发邮件还是先打游戏?

image.png 这种情况显而易见,是先发邮件后打游戏,因为不存在锁的争抢。

  1. sendEmail方法线程暂停3秒,是先发邮件还是先打游戏? 将方法sendEmail修改成如下图:

image.png

再次执行,如下图:

image.png 锁的是同一个MyResource对象,所以执行sendMail时会阻塞playGame方法

  1. 调用非同步方法hello方法和发邮件,是先发邮件还是先hello?

image.png 先输出非同步方法hellow,因为非同步方法不会被阻塞,加锁只是将同步方法阻塞

  1. 有两个MySource对象,分别调用发邮件和打游戏,请问是先发邮件还是先打游戏?

image.png 分别锁了两个对象,所以是两把锁,由于sendMail发邮件被阻塞3秒,所以在一秒后会先输出打游戏在输出发邮件

  1. 有两个静态同步方法一个MyResource对象,是先发邮件还是先打游戏?

image.png 在静态sendMailStatic内加入线程休眠又会出现什么情况,如下图,使得当前调用sendMailStatic方法的线程休眠3秒

image.png 再次执行,结果依然还是和上面一样,只不过是阻塞3秒之后先发邮箱在打游戏,这是因为锁的是静态方法,锁的其实是class,MyResource类模板,所以始终会阻塞静态同步方法

  1. 有两个静态同步方法两个MyResource对象,是先发邮件还是先打游戏? 执行结果如下图,还是先阻塞3秒先执行发邮件在执行打游戏

image.png 其实和上面的一样,不管你几个MyResource对象你始终都是一个class模板,静态同步方法锁的是class模板对象所以始终会阻塞静态同步方法

  1. 有一个静态同步方法,一个普通同步方法,一个MyResource对象,是先发邮件还是先打游戏?

image.png 普通同步方法锁的是MyResource对象,静态同步方法锁的是class模板对象,一个是对象锁一个是类锁不存在锁竞争也就不会出现阻塞,只是因为发送邮件的静态方法是被阻塞3秒所以先输出普通同步方法

  1. 有一个静态同步方法,一个普通同步方法,两个MyResource对象,是先发邮件还是先打游戏?

image.png 这里和上面雷同