• synchronized和lock的区别


    一、共同点

    当出现互斥资源时,期望一段代码同时只能一个线程访问,如商品抢购活动,多线程同时操作数据库可能导致数据错误。

    二、区别

    1. synchronized 是JVM内置的关键字,Lock是java.util.concurrent.Locks 包下的一个接口。

    2. synchronized 不管是否出现异常,会自动释放锁;Lock需要手动释放锁,尤其是在出现异常时,一定要在finally中手动释放,否则将出现死锁。

    3. synchronized 不可中断,Lock可以中断。

    4. synchronized 无法自动获得锁是否成功。

      2.1 synchronized 使用

      一个类有一个类锁,一个对象有一个对象锁。

      synchronized 可修饰以下几种情况。

      • 修饰代码块,被修饰的代码块使用{}包含,获得对象锁。
      • 修饰方法,作为范围为整个方法,获得对象锁
      • 修饰静态方法,获得类锁。
      • 修饰类,获得类锁。

      1、修饰代码块

      ​ 一个线程访问一个对象中的synchronized(this)同步代码块时,第一个线程获得锁成功访问,其他线程被阻塞,等待获得锁的线程执行完后自动释放锁。(多个线程必须是同一对象访问同步代码块)

     @PostMapping("/testsynchronized")
     public ApiResult testsynchronized() throws InterruptedException {
         synchronized (this){
         System.out.println(Thread.currentThread().getName()+"进入同步代码块");
         Thread.sleep(5000);
         System.out.println(Thread.currentThread().getName()+"同步代码块结束");
         }
     }
    

    2、修饰方法

    ​ 作用跟修饰代码块相同,作用范围为整个方法

     @PostMapping("/testsynchronized")
     public ApiResult testsynchronized() throws InterruptedException {
         testsynchronizedMothd();
     }
     
     private synchronized void testsynchronizedMothd() throws InterruptedException {
            System.out.println(Thread.currentThread().getName()+"进入同步方法");
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName()+"同步方法结束");
        }
    

    3、修饰静态方法

    由于静态方法属于类所有,和修饰方法的区别在于同一个类的所有对象访问该方法都将互斥,竞争类锁。

    4、修饰类

    在方法中使用synchronized(类名.class) 同样活动类锁。

    class ClassName {
       public void method() {
          synchronized(ClassName.class) {
             
          }
       }
    }
    

    2.2 .Lock的用法

    Lock是一个接口,有很多实现类,常用的有ReentrantLock

    Lock一些常用的方法。

    1. lock();获得锁,成功则执行同步代码,不成功则阻塞。

      private Lock lock = new ReentrantLock();
      @PostMapping("/testsynchronized")
      public ApiResult testsynchronized() throws InterruptedException {
          lock.lock();
          System.out.println(Thread.currentThread().getName()+"上锁成功");
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }finally {
              System.out.println(Thread.currentThread().getName()+"释放锁");
              lock.unlock();
          }
      }
      
    2. tryLock();有返回值,获得锁成功返回true,否则返回false。

      private Lock lock = new ReentrantLock();
      @PostMapping("/testsynchronized")
      public ApiResult testsynchronized() throws InterruptedException {
              if(lock.tryLock()){
                  System.out.println(Thread.currentThread().getName()+"上锁成功");
                  try {
                      Thread.sleep(5000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }finally {
                      System.out.println(Thread.currentThread().getName()+"释放锁");
                      lock.unlock();
                  }
              }else{
                  System.out.println(Thread.currentThread().getName()+"获取锁失败");
              }
      }
      
    3. tryLock(long time, TimeUnit unit);有返回值,活动锁成功则返回true,不成功不会马上返回,会在传入的时间内不断的尝试获得锁,期间获得锁成功返回true,如果时间结束都还没活动所则返回false。

      private Lock lock = new ReentrantLock();
      @PostMapping("/testsynchronized")
      public ApiResult testsynchronized() throws InterruptedException {
           boolean tryLock = lock.tryLock(5,TimeUnit.SECONDS);
              if(tryLock){
                  System.out.println(Thread.currentThread().getName()+"上锁成功");
                  try {
                      Thread.sleep(5000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }finally {
                      System.out.println(Thread.currentThread().getName()+"释放锁");
                      lock.unlock();
                  }
              }else{
                  System.out.println(Thread.currentThread().getName()+"获取锁失败");
              }
      }
      
    4. lockInterruptibly(),同样会阻塞,区别在于如果线程在等待,这个线程可以响应中断,即中断线程的等待状态。

  • 相关阅读:
    2017-2018-1 20155301 20155307 20155339 《信息安全系统设计基础》 实验一 开发环境的熟悉
    《JAVA程序设计》第八周学习总结
    实验二《Java面向对象程序设计》实验报告
    《JAVA程序设计》第七周学习总结
    《JAVA程序设计》结对编程联系_四则运算(第二周:整体性总结)
    《JAVA程序设计》第六周学习总结
    实验一《Java开发环境的熟悉》实验报告
    《JAVA程序设计》结对编程联系_四则运算(第一周:阶段总结)
    《JAVA程序设计》第五周学习总结
    《JAVA程序设计》第四周学习总结
  • 原文地址:https://www.cnblogs.com/puxuebing/p/15843017.html
Copyright © 2020-2023  润新知