《Java后端知识体系》系列之并发编程基础(三)锁的概述(悲观锁、乐观锁、公平锁、非公平锁、独占锁、共享锁、自旋锁)

最近深究并发编程的文章,看一点总结一点,也不算总结,就是把自己觉得有用的抄下来,对几个月后的面试希望有帮助!!

锁的概述

  • 悲观锁与乐观锁

    • 悲观锁:悲观锁是数据对外界的修改保持保守的态度,认为数据会被其它线程修改,所以每次对数据做处理时都会加锁,并且处理数据过程中数据也处于锁定状态。
      • 实现方法:Java中的synchronized锁以及lock锁都是悲观锁。
    • 乐观锁:乐观锁相对于悲观锁来说,认为数据在一般情况下并不会造成冲突,所以访问数据时并不会加入排他锁,而是在数据提交更新时,才会对验证数据是否冲突。
      • 实现方法:乐观锁的实现方式有CAS,以及版本控制(添加version字段来控制更新次数)
  • 公平锁与非公平锁

    • 公平锁:公平锁时指线程获取锁的顺序是按照线程请求锁的顺序来执行的,也就是先请求锁的线程先获得锁
      • 实现方法:ReentrantLock提供了公平锁,实现方式为ReentrantLock lock = new ReentrantLock(true)
    • 非公平锁:非公平锁是在运行时进行竞争,谁竞争到锁就是谁的,也就是先来不一定先得。
      • 实现方法:ReentrantLock也提供了非公平锁的实现方式,ReentrantLock lock = new ReentrantLock(false)。如果构造函数不传递参数,默认是非公平锁。synchronized也是非公平锁,当线程释放锁时,处于就绪态的线程会竞争获得锁(自旋的方式)。
    • 总结:没有公平性需求的前提下尽量使用非公平锁,因为公平锁会带来性能开销。
  • 独占锁与共享锁

    • 独占锁:独占锁是任何时候都只有一个线程可以得到锁,独占锁是一种悲观锁,每次访问资源都会先加上互斥锁,这样限制了并发性,因为读操作并不会影响数据的一致性,而独占锁同一时刻由一个线程读取数据,其它线程必须等待当前线程释放锁之后才能进行读取。
      • 实现方式:ReentrantLock是独占锁,synchronized也是独占锁。
    • 共享锁:共享锁是可以由多个线程持有。共享锁其实是一种乐观锁,放宽了加锁的条件,允许多个线程同时操作。
      • 实现方式:ReadWriteLock读写锁是共享锁,它允许一个资源可以被多个线程同时进行读操作。
  • 可重入锁

    • 概念:如果一个线程获得了锁,那么这个线程就可以无限次数的进入被该锁锁住的代码。

      public class Hello {
          public synchronized void helloA(){
              System.out.println("hello");
          }
      
      
          public synchronized void helloB(){
              System.out.println("hello B");
              helloA();
          }
      }
      
    • 以上代码中,调用helloB方法会提前获取内置锁,然后打印输出,之后调用helloA方法,在调用前会先获取内置锁,如果内置锁不是可重入的,那么调用线程会一直被阻塞。

    • synchronized内部锁是可重入锁,可重入锁的原理就是在内部维护一个线程标识,用来标识该锁被哪个线程占用,然后关联一个计数器,一开始计数器为0,说明该锁没有被其它线程占用,当一个线程获取了该锁时,计数器加1,这时其它线程再来获取锁时就会发现锁的持有者不是自己而被阻塞挂起。但是当获取了该锁的线程再次获取锁时发现锁的拥有者是自己,计数器会继续加1,当释放锁后计数器减1,当计数器为0时,锁里面的线程标识被重置为null,这时候其它被阻塞的线程会唤醒来竞争锁。

  • 自旋锁

    • 概念: Java中一个线程获取锁失败后会被切换到内核状态被挂起,当该线程获取到锁之后又需要从内核态切换为用户态而唤醒该线程,而从用户态切换到内核态开销是很大的,在一定程度上影响并发性能。自旋锁是当线程获取锁时,如果发现锁已经被其它线程占用,它不马上阻塞自己,在不放弃CPU使用权的情况下,多次尝试获取锁(默认次数为10,可以使用-XX:PreBlockSpinsh参数设置),很有可能后面几次尝试中其它线程已经释放了锁,如果尝试指定次数仍然没有获取到锁,则当前线程会被阻塞挂起
    • 实现方式:synchronized中就有通过自旋锁来实现竞争锁的情况。

我是会敲代码的汤姆猫!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章