JUC(二)——深入理解锁机制

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对象。
  • 不同的锁之间或不干扰,上锁的方法和没上锁的方法或不干扰
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值