Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

1. 锁分类

  • 乐观锁

    • 认为当前线程修改“共享内存数据”时,应该不会有其他线程去修改同一份数据
      • 所以操作过程“不会加锁”
    • 例子
      • CAS——比较并变换
        • 比较 内存中的数据值 和 期望的值 是否相同,只有相同时才会更新
        • 需要依赖底层 CPU 的 cmpxchg 指令,因为要把比较与更新绑定为一整个原子操作,防止中途被分片切走导致判断过时
  • 悲观锁

    • 认为当前线程修改“共享内存数据”时,一定会有其他线程来修改
      • 所以操作过程“必须先加锁”
    • 例子
      • Java 中的 Sychronized 和 ReentrantLock
  • 公平锁

    • 如果当前锁已经被某个线程持有,那新来的线程就要去排队
  • 非公平锁

    • 如果当前锁已经被某个线程持有,那新来的线程可以先用 CAS 抢一下,抢到了就能往下执行,抢不到再去排队
    • ReentrantLock 默认是非公平锁,但可以改为公平锁
  • 重入锁

    • 如果一个线程已经获取到了锁,那这个线程下次进入同步代码时,可以直接进入,不用重新获取锁
    • sychronized 和 ReentrantLock 都是可重入锁
  • 非重入锁

    • 即不可重入的锁
  • 独占锁

    • 如果一个线程已经获取到了锁,那其他线程不可以继续获取锁
  • 共享锁

    • 即不独占的锁

2. 锁升级

无锁->偏向锁->轻量级锁->重量级锁

  • 无锁

    • 即不加锁
    • 乐观锁的 CAS 就是一个例子
  • 偏向锁

    • 如果一个线程获取锁后,执行过程中一直没有其他线程来竞争锁,那可以让其持有一个偏向锁
    • 持有偏向锁的线程在执行时,就不再需要获取锁
    • 从而减少锁的开销
  • 轻量级锁

    • 如果一个线程想要竞争的锁很快就会被释放,那可以让其使用轻量级锁
    • 想获取轻量级锁的线程在竞争时,如果暂时获取不到,就会自旋一段时间,等待锁释放
    • 从而减少挂起唤醒和 CPU 上下文切换的开销
  • 重量级锁

    • 即一般的锁
    • 如果一个线程获取不到锁,就会被挂起,等待锁释放后被唤醒