问题
-
标准访问,先打印邮件还是短信
答案:邮件
public class Lock8 { public static void main(String[] args) { Phone p = new Phone(); new Thread(() -> { try { p.sendEmail(); } catch (Exception e) { e.printStackTrace(); } },"A").start(); new Thread(() -> { try { p.sendSMS(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } } class Phone { public synchronized void sendEmail() throws Exception { System.out.println("sendEmail"); } public synchronized void sendSMS() throws Exception { System.out.println("sendSMS"); } }
-
邮件方法暂停4秒钟,先打印邮件还是短信
1-2 解析:synchronized锁的不是当前的方法,而是当前方法所在的整个资源类,即当前这个对象this,这表示同一时间段,只允许一个线程访问资源类里面的这些synchronized方法,其它的线程都不能进入到当前对象的其它的synchronized方法
答案:邮件
public synchronized void sendEmail() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("sendEmail"); }
-
新增一个普通方法hello(),先打印邮件还是hello()
解析:普通方法和锁无关
答案:hello
public void hello(){ System.out.println("hello"); }
-
两部手机,先打印邮件还是短信
解析:换成两个对象之后,因为不是同一把锁了,所以情况立即发生变化 ,假设发邮件方法内还是睡眠4秒钟,因为变成了两个对象,互不干涉,所以先打印短信
答案:短信
public class Lock8 { public static void main(String[] args) { Phone p = new Phone(); Phone p2 = new Phone(); new Thread(() -> { try { p.sendEmail(); } catch (Exception e) { e.printStackTrace(); } },"A").start(); new Thread(() -> { try { p2.sendSMS(); } catch (Exception e) { e.printStackTrace(); } },"B").start(); } }
-
2个静态同步方法,1部手机,先打印邮件还是短信
答案:邮件
public static synchronized void sendEmail() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("sendEmail"); } public static synchronized void sendSMS() throws Exception { System.out.println("sendSMS"); }
-
2个静态同步方法,2部手机,先打印邮件还是短信
5-6解析:所有的静态同步方法用的都是同一把锁类对象本身,一旦一个静态同步方法获取到锁后,其它的静态同步方法都必须等待该方法释放锁后才能获取锁
答案:邮件
代码:参考第4
-
1个静态同步方法,1个普通同步方法,1部手机,先打印邮件还是短信
public static synchronized void sendEmail() throws Exception { TimeUnit.SECONDS.sleep(4); System.out.println("sendEmail"); } public synchronized void sendSMS() throws Exception { System.out.println("sendSMS"); }
解析:email锁的是Phone这个Class对象,而sms锁的是p这个实例对象,两个不冲突
答案:短信
-
1个静态同步方法,1个普通同步方法,2部手机,先打印邮件还是短信
解析:即使换成两个手机对象,来分别调用邮箱、短信,也不会对锁产生影响
答案:短信
代码:参考第4、第7
总结
Java中的每一个对象都可以作为锁。具体表现为以下3种形式。
- 对于普通同步方法,锁是当前实例对象。
- 对于静态同步方法,锁是当前类的Class对象。
- 对于同步方法块,锁是Synchronized括号里配置的对象