JUC(一)——Locks
JUC(二)——深入理解锁机制
JUC(三)——线程安全类
JUC(四)——强大的辅助类讲解
JUC(五)——Callable
JUC(六)——阻塞队列
JUC(七)——线程池简单使用
JUC(八)——线程池深入讲解
对于锁大家肯定都不陌生,锁分为synchronize和lock
但是大家是否知道锁到底锁住的是什么呢?
接下来我们举几个例子来了解锁(这里使用synchronize来演示)
- 1、该代码先打印的是短信还是邮件?
class Phone { public synchronized void sendSMS() throws Exception { System.out.println("------短信"); } public synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:短信(我们结合第二个例子一起解释)
- 2、停4秒在短信方法内,该代码先打印的是短信还是邮件?
-
class Phone { public synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:短信
- 讲解:
- 一个对象里面如果有多个被synchronize锁住的普通方法,如果某一个时刻内,只要有一个线程去调用其中的一个synchronized方法了,那么其它的线程都只能等待
- 换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法
- 此时锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
-
- 3、普通的hello方法,该代码先打印短信还是hello
-
class Phone { public synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone.getHello(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:hello
- 结论: 普通方法和同步锁无关
-
- 4、现在有两部手机,该代码先打印的是短信还是邮件?
-
class Phone { public synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); Phone phone2 = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone2.getHello(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:邮件
- 结论: 锁的是对象,两个不同的对象是互不影响的
-
- 5、两个静态同步方法,1部手机,该代码先打印的是短信还是邮件?
-
class Phone { public static synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public static synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:短信(和下一个例子一起说)
-
- 6、两个静态同步方法,2部手机,该代码先打印的是短信还是邮件?
-
class Phone { public static synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public static synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); Phone phone2 = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone2.sendEmail(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:短信
- 结论: 对静态方法加锁,锁住的不在是对象,而是这个类。即该类中所有的静态加锁方法用的是同一把锁
-
- 7、1个静态同步方法,1个普通同步方法,1部手机,该代码先打印的是短信还是邮件?
-
class Phone { public static synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:邮件(结论和下个例子一起说)
-
- 8、1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件
-
class Phone { public static synchronized void sendSMS() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("------短信"); } public synchronized void sendEmail() throws Exception { System.out.println("------邮件"); } public void getHello() { System.out.println("------hello"); } } public class Lock { public static void main(String[] args) throws Exception { Phone phone = new Phone(); Phone phone2 = new Phone(); new Thread(() -> { try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } }, "AA").start(); Thread.sleep(100); new Thread(() -> { try { phone2.sendEmail(); } catch (Exception e) { e.printStackTrace(); } }, "BB").start(); } }
- 结果:邮件
- 结论: 静态加锁锁的是类,普通加锁方法锁的是对象,两个锁互不干扰
-
总结
- 对于普通同步方法,锁是当前实例对象。
- 对于静态同步方法,锁是当前类的Class对象。
- 不同的锁之间或不干扰,上锁的方法和没上锁的方法或不干扰