Java 多线程中用 synchronized 加锁的八锁问题

  1. 看以下代码,有一个 phone 对象,A、B 线程分别调用该对象的方法,问两个方法谁先调用?答:先发短信再打电话,因为 synchronized 锁住的是 phone 对象(锁的对象是方法调用者)。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();

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

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

class Phone {
    synchronized void sendMsg() {
      	System.out.println("发短信");
    }

    synchronized void call() {
        System.out.println("打电话");
    }
}
  1. 看以下代码,有一个 phone 对象,A、B 线程分别调用该对象的方法,问两个方法谁先调用?答:先发短信再打电话,理由还是 synchronized 锁住的是 phone 对象,从 A 线程开始执行方法时到 A 执行完毕,B 线程一定会等待 4 秒。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();

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

    TimeUnit.SECONDS.sleep(1);

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

class Phone {
    synchronized void sendMsg() {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized void call() {
        System.out.println("打电话");
    }
}
  1. 看以下代码,一个对象,俩线程分别执行有锁和无锁的方法,问两个方法谁先调用?答:先打电话再发短信,没有加锁的方法不受锁的影响,该调用还是调用。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();

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


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

class Phone {
    synchronized void sendMsg(){
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    void call() {
        System.out.println("打电话");
    }
}
  1. 看以下代码,两个对象,两个线程分别执行有锁和无锁的方法,问两个方法谁先调用?答:先打电话再发短信,当 A 线程开始执行时,等待一秒钟 B 线程的方法就执行,两个对象两把锁,互不影响。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();
    Phone phone2 = new Phone();

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

    TimeUnit.SECONDS.sleep(1);

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

class Phone {
    synchronized void sendMsg(){
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized void call() {
        System.out.println("打电话");
    }
}
  1. 两个线程分别调用两个静态加锁方法,问两个方法谁先调用?答:先发短信再打电话,两个方法加了 static ,上升到类级别,也就是说锁的是 phone 的 class,是一个类对象,在 A 线程调发短信方法时持有该 class,B 线程当然获取不到该 class,必须等待。
public static void main(String[] args) throws InterruptedException {
    
    new Thread(() -> {
        Phone.sendMsg();
    }, "A").start();

    new Thread(() -> {
        Phone.call();
    }, "B").start();
}

class Phone {
    static synchronized void sendMsg(){
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static synchronized void call() {
        System.out.println("打电话");
    }
}
  1. 两个对象,两个线程分别调用两个静态加锁方法,问两个方法谁先调用?答:还是发短信再打电话,锁的是 phone 的类对象,两个 phone 对象所属的 class 是一致的,在 A 线程调发短信方法时持有该 class,B 线程获取不到该 class,必须等待。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();
    Phone phone2 = new Phone();

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

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

class Phone {
    static synchronized void sendMsg(){
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static synchronized void call() {
        System.out.println("打电话");
    }
}
  1. 一个对象,先调用静态加锁方法,再调用成员加锁方法,问两个方法谁先调用?答:先打电话再发短信,加了 static 方法锁的对象是 phone 的 class,而未加 static 的方法锁的是原本的 phone 对象,锁的对象不同,并不互斥。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();

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

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

class Phone {
    static synchronized void sendMsg(){
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized void call() {
        System.out.println("打电话");
    }
}
  1. 两个对象,先调用静态加锁方法,再调用成员加锁方法,问两个方法谁先调用?答:还是打电话再发短信,static 方法锁的是 class 对象,未加 static 的方法锁的是 phone2 对象,并不互斥。
public static void main(String[] args) throws InterruptedException {
    Phone phone = new Phone();
    Phone phone2 = new Phone();

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

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

class Phone {
    static synchronized void sendMsg(){
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("发短信");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized void call() {
        System.out.println("打电话");
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值