资源类:
class Phone{ public synchronized void sendEmail() throws Exception{ System.out.println("-----------Email"); } public synchronized void sendSMS() throws Exception{ System.out.println("-----------SMS"); } }
线程操作资源类
public class LockDemo { 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); //为了保证先A再B new Thread(()->{ try { phone.sendSMS(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } }
问题:
标准访问,请问先打印Email还是SMS
先打印Email,再打印SMS
邮件方法暂停4s,请问先打印Email还是SMS
class Phone{ public synchronized void sendEmail() throws Exception{ Thread.sleep(4000); System.out.println("-----------Email"); } public synchronized void sendSMS() throws Exception{ System.out.println("-----------SMS"); } }
先打印Email,再打印SMS
新增一个普通方法hello,请问先打印hello还是email
class Phone{ public synchronized void sendEmail() throws Exception{ Thread.sleep(4000); System.out.println("-----------Email"); } public synchronized void sendSMS() throws Exception{ System.out.println("-----------SMS"); } public void sayHello() throws Exception{ System.out.println("-----------Hello"); } }
public class LockDemo { 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.sayHello(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } }
先打印Hello,隔4s后再打印Email
两部手机,先打印Email,还是SMS(Email内休息4s)
public class LockDemo { public static void main(String[] args) throws Exception { Phone phone = new Phone(); Phone phone2 = new Phone(); new Thread(()->{ try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } },"A").start(); Thread.sleep(100); new Thread(()->{ try { phone2.sendSMS(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } }
先打印SMS,隔4s再打印Email
两个静态同步方法,同一个手机,先打印Email,还是SMS
class Phone{ public static synchronized void sendEmail() throws Exception{ Thread.sleep(4000); System.out.println("-----------Email"); } public static synchronized void sendSMS() throws Exception{ System.out.println("-----------SMS"); } }
先打印Email,再打印SMS
两个静态同步方法,2部手机,先打印Email,还是SMS
public class LockDemo { public static void main(String[] args) throws Exception { Phone phone = new Phone(); Phone phone2 = new Phone(); new Thread(()->{ try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } },"A").start(); Thread.sleep(100); new Thread(()->{ try { phone2.sendSMS(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } }
先打印Email,再打印SMS
一个静态同步方法,一个普通同步方法,一个手机,先打印Email还是SMS
class Phone{ public static synchronized void sendEmail() throws Exception{ Thread.sleep(4000); System.out.println("-----------Email"); } public synchronized void sendSMS() throws Exception{ System.out.println("-----------SMS"); } }
public class LockDemo { 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(); } }
先打印SMS,隔四秒再打印Email
一个静态同步方法,一个普通同步方法,2个手机,先打印Email还是SMS
public class LockDemo { public static void main(String[] args) throws Exception { Phone phone = new Phone(); Phone phone2 = new Phone(); new Thread(()->{ try { phone.sendEmail(); } catch (Exception e) { e.printStackTrace(); } },"A").start(); Thread.sleep(100); new Thread(()->{ try { phone2.sendSMS(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } }
先打印SMS,隔四秒再打印Email
锁结论:
对于非静态同步方法
所有的非静态同步方法都是用的同一把锁 ==> 实例对象本身
一个对象里面如果有多个synchronized方法,某一时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一的一个线程去访问这些synchronized方法
如果一个实例对象的非静态同步方法获取锁后,该实例对象的其它非静态同步方法必须等待 当前获取锁的方法 释放锁后才能获取锁
对于多个线程去访问同一类下不同实例对象的非静态同步方法时,不需要去等待锁被释放,因为此时的锁并不是同一个
对于静态同步方法
所有的静态同步方法,锁 ==> 类的class (发射机制)
一个静态同步方法获取锁后,其他的静态同步方法必须等待该方法释放锁后才能获取锁,此时不需要关心是否是同一个实例对象,只要它们属于这个类即可
但是非静态同步方法的锁和静态同步方法的锁是两个不同的对象,这两种方法之间不会存在竞争关系
对于同步代码块
所有同步代码块synchronized(){},锁 ==> ()中配置的对象
当一个线程访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁
原文:https://www.cnblogs.com/pikachu511/p/14452263.html