avatar

目录
锁之8锁

利用8道先执行发送邮件方法还是发送短信方法的题,搞定锁这个概念!

  1. 标准的访问情况下,先执行 sendEmail 还是 sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

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

    new Thread(()->{
    phone.sendEmail();
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(2);

    new Thread(()->{
    phone.sendSMS();
    },"B").start();
    }
    }
    //资源类
    class Phone{
    public synchronized void sendEmail(){
    System.out.println("sendEmail");
    }

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

    小结

    • 答案:执行sendEmail方法
    • 原因:被 synchronized 修饰的方式,锁的对象是方法的调用者,所以说这里两个方法调用的对象是同一个,先调用的先执行!
  2. sendEmail休眠3秒后 ,先执行 sendEmail 还是 sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo02 {
    public static void main(String[] args) throws InterruptedException {
    Phone2 phone = new Phone2();

    new Thread(()->{
    try {
    phone.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(2);

    new Thread(()->{
    phone.sendSMS();
    },"B").start();
    }
    }

    class Phone2{
    public synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(3);
    System.out.println("sendEmail");
    }

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

    小结:

    • 答案:执行sendEmail方法
    • 原因:被 synchronized 修饰的方式,锁的对象是方法的调用者,所以说这里两个方法调用的对象是同一个,先调用的先执行!
  3. 增加一个普通方法,请问先打印那个 sendEmail 还是 hello
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo03 {
    public static void main(String[] args) throws InterruptedException {
    Phone3 phone = new Phone3();

    new Thread(()->{
    try {
    phone.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(1);

    new Thread(()->{
    phone.hello();
    },"B").start();
    }
    }

    class Phone3{
    public synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(4);
    System.out.println("sendEmail");
    }

    // 没有 synchronized 没有 static 就是普通方式
    public void hello(){
    System.out.println("hello");
    }
    }

    小结:

    • 答案:执行hello方法
    • 原因:新增加的这个方法没有 synchronized 修饰,不是同步方法,不受锁的影响!
  4. 两个手机(对象),请问先执行sendEmail 还是 sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo04 {
    public static void main(String[] args) throws InterruptedException {
    Phone4 phone1 = new Phone4();
    Phone4 phone2 = new Phone4();

    new Thread(()->{
    try {
    phone1.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(1);

    new Thread(()->{
    phone2.sendSMS();
    },"B").start();
    }
    }

    class Phone4{
    public synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(3);
    System.out.println("sendEmail");
    }

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

    小结:

    • 答案:执行sendSMS方法
    • 原因:被 synchronized 修饰的方式,锁的对象是调用者;我们这里有两个调用者,两个方法在这里是两个锁
  5. 两个静态同步方法,同一个手机请问先执行sendEmail 还是 sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo05 {
    public static void main(String[] args) throws InterruptedException {
    Phone5 phone = new Phone5();


    new Thread(()->{
    try {
    phone.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(1);

    new Thread(()->{
    phone.sendSMS();
    },"B").start();
    }
    }

    class Phone5{

    public static synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(3);
    System.out.println("sendEmail");
    }

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

    }

    小结

    • 答案:执行sendEmail方法
    • 原因:只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!所以说这里是同一个锁,并不是因为synchronized的修饰而改变
  6. 两个静态同步方法,两个手机,请问先执行sendEmail 还是 sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo06 {
    public static void main(String[] args) throws InterruptedException {
    Phone6 phone = new Phone6();
    Phone6 phone2 = new Phone6();

    new Thread(()->{
    try {
    phone.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(1);

    new Thread(()->{
    phone2.sendSMS();
    },"B").start();
    }
    }

    class Phone6{

    public static synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(3);
    System.out.println("sendEmail");
    }

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

    }

    小结:

    • 答案:执行sendEmail方法
    • 原因:只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!所以说这里是同一个锁,并不是因为synchronized而改变
  7. 一个普通同步方法,一个静态同步方法,只有一个手机,请问先执行sendEmail 还是sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo07 {
    public static void main(String[] args) throws InterruptedException {
    Phone7 phone = new Phone7();

    new Thread(()->{
    try {
    phone.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(1);

    new Thread(()->{
    phone.sendSMS();
    },"B").start();
    }
    }

    class Phone7{

    public static synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(3);
    System.out.println("sendEmail");
    }

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

    }

    小结:

    • 答案:执行sendSMS方法
    • 原因:synchronized 锁的是这个调用的对象,static 锁的是这个类的Class模板,这里是两个锁!
  8. 一个普通同步方法,一个静态同步方法,两个手机,请问先执行sendEmail 还是 sendSMS
    java
    package com.dakuzai.lockDemoTest;

    import java.util.concurrent.TimeUnit;

    public class LockDemo08 {
    public static void main(String[] args) throws InterruptedException {
    Phone8 phone = new Phone8();
    Phone8 phone2 = new Phone8();

    new Thread(()->{
    try {
    phone.sendEmail();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    },"A").start();

    //Thread.sleep(200);
    TimeUnit.SECONDS.sleep(1);

    new Thread(()->{
    phone2.sendSMS();
    },"B").start();
    }
    }

    class Phone8{

    public static synchronized void sendEmail() throws InterruptedException {
    TimeUnit.SECONDS.sleep(3);
    System.out.println("sendEmail");
    }

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

    }

    小结:

    • 答案:执行sendSMS方法
    • 原因:synchronized 锁的是这个调用的对象,static 锁的是这个类的Class模板,这里是两个锁!

总结

  1. new + this 调用的这个对象,是一个具体的对象!

  2. static修饰class 唯一的一个模板!

在我们编写多线程程序得时候,只需要搞明白这个到底锁的是什么就不会出错了!

文章作者: minghui
文章链接: https://dakuzai.ml/2020/03/14/%E9%94%81%E4%B9%8B8%E9%94%81/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Dakuzai’s Blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论