多线程8锁问题


Java的8锁问题链接

8锁即8个关于锁执行顺序的问题


解决问题前,首先需要明白的是 synchronized 只会锁两样东西,一样是调用的对象,一样是Class


一个对象里面如果有多synchronized方法,某一时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一时刻内,只能唯一一个线程去访问这些synchronized方法。锁的是当前对象this,被锁定后,其它的线程不能进入到当前对象的其它的synchronized方法

synchronized实现同步锁的基础:Java中的每一个对象都可以作为锁。
具体表现为以下3种形式:
对于普通同步方法,锁是当前实例对象
对于静态同步方法,锁是当前类的class 对象。
对于同步方法块,锁是synchronized括号里配置的对象。


问题一: 标准访问,请问先打印邮件还是短信?

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

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(1000);

        new Thread(()->{
            try{
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

判断执行顺序,先判断什么被锁了,这里synchronized锁的是Phone对象new出来的phone,因为先调用了sendEmail()睡1秒后调用的sendSMS(),sendSMS()需要等到sendEmail()释放锁后才会执行

输出结果
------sendEmail
------sendSMS

问题二:邮件暂停4秒钟,请问先打印邮件还是短信?

class Phone {
    public synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }
    public synchronized void sendSMS() throws Exception {
        System.out.println("------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

该情况其实和问题一 一样,synchronized锁的是Phone对象new出来的phone,当调用sendEmail()时,phone被锁,而程序不受sendEmail()内睡的影响继续执行,在调用sendSMS()的时候因为phone被锁导致等待,当sendEmail()执行完后sendSMS()瞬间执行

输出结果
------sendEmail
------sendSMS

问题三:新增一个普通方法hello(),请问先打印邮件还是hello?

class Phone {
    public synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }

    public void hello(){
        System.out.println("------hello");
    }

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone.hello();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

程序执行在sendEmail()中锁了fun并在方法中睡4秒,外部在睡1秒后调用hello(),因为无锁因此直接执行

输出结果
------hello
------sendEmail

问题四:两部手机,请问先打印邮件还是短信?

class Phone {
    public synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }
    public synchronized void sendSMS() throws Exception {
        System.out.println("------sendSMS");
    }
    
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        Phone phone1=new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone1.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

程序调用sendEmail()时锁住phone,外部睡1秒后调用sendSMS()时锁phon1,互不影响

输出结果
------sendSMS
------sendEmail

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

class Phone {
    public static synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }
    public static synchronized void sendSMS() throws Exception {
        System.out.println("------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

这里多了静态static,因此此时锁的东西改变了,sendEmail()和sendSMS()都是锁的Phone这个class,程序在执行sendEmail()时锁住Phone class,睡1秒后调用sendSMS(),sendSMS()等待sendEmail()内睡完释放锁后再执行

输出结果
------sendEmail
------sendSMS

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

class Phone {
    public static synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }
    public static synchronized void sendSMS() throws Exception {
        System.out.println("------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        Phone phone1=new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone1.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

要注意的是,不管现在new结果对象,调用方法后锁的都是Phone class,sendSMS()会被sendEmail()阻塞

输出结果
------sendEmail
------sendSMS

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

class Phone {
    public static synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }
    public synchronized void sendSMS() throws Exception {
        System.out.println("------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

同样只要确认锁的是不是一个东西就知道会不会阻塞,调用sendEmail()时阻塞的是Phone class,调用sendSMS()时阻塞的是phone

输出结果
------sendSMS
------sendEmail

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

class Phone {
    public static synchronized void sendEmail() throws Exception {
        try {
            TimeUnit.SECONDS.sleep(4);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("------sendEmail");
    }
    public synchronized void sendSMS() throws Exception {
        System.out.println("------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        Phone phone1 = new Phone();
        new Thread(()->{
            try{
                phone.sendEmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(()->{
            try{
                phone1.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

解题跟问题七一致,调用sendEmail()时阻塞的是Phone class,调用sendSMS()时阻塞的是phon1

输出结果
------sendSMS
------sendEmail
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值