Java中的锁

Java中的锁

锁的基本概念

高并发场景下,因数据一致性问题,需要通过锁来解决

锁的分类

  • 乐观锁&悲观锁
    1. 乐观锁
      • 本质上不加锁,通过CAS、版本号等方式进行比较和重试,避免了内核态切换的开销,线程不会阻塞
      • Java中的乐观锁有Atomic原子类
      • MySQL实现乐观锁的方式有加版本号
      • 存在ABA的问题,可以通过加版本号解决
    2. 悲观锁
      • 保证同一时间只有一个线程能拿到锁,后续线程会阻塞,开销比较大,通过Synchronized、Lock、实时读等方式实现悲观锁
      • Java中的悲观锁有Synchronized、Lock
      • MySQL中实现悲观锁的方式有实时读、写锁
  • 可重入锁&不可重入锁
    1. 可重入锁指的是对于同一个对象可以有多个线程拿到锁,Java中大部分都是可重入锁
    2. 不可重入锁指的是一个对象只能有一个线程拿到锁,容易造成死锁的问题。
  • 公平锁&非公平锁
    1. 公平锁:线程排队拿锁,性能比较好
    2. 非公平锁:线程可以插队拿锁,开销比较大
  • 读锁&写锁
    1. 读锁:共享锁,多个线程可以同时获取,不会阻塞
    2. 写锁:独占锁,同一时间只能有一个线程持有,后续线程会阻塞
  • 精简版
    • 乐观锁:无锁 CAS,无阻塞,有 ABA;原子类、version 版本;
    • 悲观锁:加锁阻塞,开销大;synchronized、Lock、mysql 行锁;
    • 可重入:同一线程重复拿锁不死锁;
    • 公平锁排队、性能低;非公平可插队、吞吐量高;
    • 读锁共享、写锁独占,读多写少场景用读写锁。