synchonized 解析

  1. synchronized 的原理是什么

    • 通过 monitorentre 和 moniterexit 两个 cup 指令配合使用,执行 monitorentre 获得锁,执行 monitorexit 释放锁
  2. synchronized 的几种状态

    • 无锁,object head 中标志: biased_lock: 0, lock: 00
    • 偏向锁,object head 中标志: biased_lock: 1, lock: 01
    • 轻量级锁,object head 中标志: biased_lock: 0, lock: 01
    • 重量级锁,object head 中标志: biased_lock: 0, lock: 10
  3. 偏向锁解析

    1. 偏向锁出现的原因

      • 在大多数时候,锁都不存在多线程竞争,而且总是由同一个线程获得,为了减少不必要的轻量级锁出现,才引入了偏向锁
    2. 偏向锁的实现

      image.png

    * 线程尝试获取偏向锁,发现 mark word 为 101 表示,可以偏向,将自己的线程 id 100 用 CAS 设置到 mark word 
    * 线程 100 再次执行该方法,发现可以偏向 101 可以偏向,一看 mark word 中的 thread id 和自己相同,则进入该方法 

    * 线程 101 执行该方法,发现可以偏向 101 为可以偏向,CAS 将 thread id 指向自己,发现失败了,因为 thread id 已经指向 100 了,接下来回去执行撤销偏向锁的步骤
    * 在一个全局 safe pinter 的地方暂停持有该偏向锁的线程 100,检查线程 100 的状态,此时有两种情况
    * 1.  线程 100 已经终止状态,那么将 Mark Word 的线程 ID 置位空后,CAS 将线程 ID 偏向线程 B 然后就又回到上述又是偏向锁线程的运行状态了
      2. 线程 100 处于活跃状态,那么将偏向锁升级为轻量级锁,然后唤醒线程 100 继续执行操作,线程 101 自旋获取轻量级锁
  1. 轻量级锁解析

    1. 轻量级锁出现的原因

      • 如果线程之间不存在竞争或者偶尔出现竞争关系,如果同步代码块执行的很快,轻量级锁还是也能有效率的
    2. 轻量级锁实现原理

      • CAS + 自旋等待
    3. 轻量级锁加锁实现步骤

      • 需要获取锁的线程在栈空间创建存储锁记录的空间
      • 将锁对象头的 mark word 复制到栈上的锁记录空间
      • 用 CAS 尝试修改对象头的 mark word ,指向栈上创建的存储锁记录的空间
      • 如果 CAS 修改成功,则表示线程获得锁
      • 如果 CAS 修改失败,则表示由竞争关系,尝试自旋等待获取锁
      • 如果自旋等待成功,则获取锁
      • 如果自旋等待失败,则将轻量级锁升级为重量级锁
    4. 轻量级锁解锁步骤

      • 使用 CAS 将栈空间的 mark word 替换对象头
      • 如果替换成功,表示没有竞争状态或者轻量级锁没有升级为重量级锁,成功解锁
      • 如果替换失败,表示存在竞争关系,轻量级锁已经被其他线程升级为重量级锁,
      • 释放锁,唤醒正在等待的线程
  2. 如果一个对象拥有两个 synchronized 代码块 A,B, 当他拿到执行代码块 A 的锁是,如果想执行 B,可以直接执行,因为 synchronized 锁的是对象

你可能感兴趣的:(synchonized 解析)