准备工作
创建一个资源类Phone(手机), 里面两个方法sendEmail(发邮件), sendSMS(发短信), 都是线程同步方法
class Phone {
public synchronized void sendSMS() {
System.out.println("------sendSMS");
}
public synchronized void sendEmail() {
System.out.println("------sendEmail");
}
}
根据我们以下八种情况来进行调用
-
标准访问, 两个线程, 各自访问一个方法
public class EightLocks { public static void main(String[] args) throws InterruptedException { Phone phone = new Phone(); new Thread(()->{ phone.sendSMS(); }, "AA").start(); Thread.sleep(100); new Thread(()->{ phone.sendEmail(); }, "BB").start(); } }
打印结果
------sendSMS
------sendEmail -
在sendSMS方法中停留4秒, 其余与第一种情况一样
public static synchronized void sendSMS() throws InterruptedException { //停留4秒 TimeUnit.SECONDS.sleep(4); System.out.println("------sendSMS"); }
打印结果
------sendSMS
------sendEmail1-2情况说明:
- 一个对象里面如果有多个synchronized方法, 某一个时刻内, 只要一个线程去调用其中的一个synchronized方法了, 其它的线程都只能等待, 换句话说,某一个时刻内, 只能有唯一的一个线程去访问这些synchronized方法
- 锁的是当前对象this, 被锁定后, 其它的线程都不能进入到当前对象的其它的synchronized方法
-
新增普通方法hello(), 第一个线程调用sendSMS(), 第二个线程调用hello()
//资源类中增加 public void hello() { System.out.println("------getHello"); } //主类中修改 new Thread(()->{ phone.hello(); }, "BB").start();
打印结果
------hello
------sendSMS -
创建两个Phone实例, 一个调用sendSMS, 一个调用sendEmail
public class EightLocks { public static void main(String[] args) throws InterruptedException { Phone phone1 = new Phone(); Phone phone2 = new Phone(); new Thread(()->{ phone1.sendSMS(); }, "AA").start(); Thread.sleep(100); new Thread(()->{ phone2.sendEmail(); }, "BB").start(); } }
打印结果
------sendEmail
------sendSMS
3-4情况说明:
- 普通方法与锁无关, 不会被阻塞
- 两个实例对象不是同一把锁
-
将sendSMS()和sendEmail()变成静态方法, 一个实例对象去调用
class Phone { public static synchronized void sendSMS() { System.out.println("------sendSMS"); } public static synchronized void sendEmail() { System.out.println("------sendEmail"); } } public class EightLocks { public static void main(String[] args) throws InterruptedException { Phone phone = new Phone(); new Thread(()->{ phone.sendSMS(); }, "AA").start(); Thread.sleep(100); new Thread(()->{ phone.sendEmail(); }, "BB").start(); } }
打印结果
------sendSMS
------sendEmail
-
两个实例对象调用静态方法
public class EightLocks { public static void main(String[] args) throws InterruptedException { Phone phone1 = new Phone(); Phone phone2 = new Phone(); new Thread(()->{ phone1.sendSMS(); }, "AA").start(); Thread.sleep(100); new Thread(()->{ phone2.sendEmail(); }, "BB").start(); } }
打印结果
------sendSMS
------sendEmail
5-6情况说明:
- 对于普通方法来说, 锁的对象是this, 也就是当前实例对象
- 对于静态方法来说, 锁的对象就是当前类的Class对象, 也就是说这个类的所有实例对象公用同一把锁
-
一个静态方法, 一个普通方法, 一个实例对象调用
class Phone { public static synchronized void sendSMS() { System.out.println("------sendSMS"); } public synchronized void sendEmail() { System.out.println("------sendEmail"); } } public class EightLocks { public static void main(String[] args) throws InterruptedException { Phone phone = new Phone(); new Thread(()->{ phone.sendSMS(); }, "AA").start(); Thread.sleep(100); new Thread(()->{ phone.sendEmail(); }, "BB").start(); } }
打印结果
------sendEmail
------sendSMS
-
一个静态方法, 一个普通方法, 两个实例对象调用
public class EightLocks { public static void main(String[] args) throws InterruptedException { Phone phone1 = new Phone(); Phone phone2 = new Phone(); new Thread(()->{ phone1.sendSMS(); }, "AA").start(); Thread.sleep(100); new Thread(()->{ phone2.sendEmail(); }, "BB").start(); } }
打印结果
------sendEmail
------sendSMS
7-8情况说明:
- 不管是一个实例对象还是多个实例对象, 普通同步方法与静态同步方法的锁都不是同一把
我的个人主页: www.ayu.link
本文连接: ┏ (゜ω゜)=☞