monsterhxw / my-notes

技术随想
MIT License
1 stars 0 forks source link

Java synchronized 的 Heavy-weight Lock (重量级锁) 源码分析 #3

Open monsterhxw opened 7 months ago

monsterhxw commented 7 months ago

synchronized 分析

膨胀成重量锁 (创建 ObjectMonitor 对象)

// case 1
CASE(_monitorenter)::bytecodeInterpreter
  |-monitorenter(thread, elem)::InterpreterRuntime
  |   |-if (UseBiasedLocking)
  |   |   |-fast_enter(h_obj, elem->lock(), true, CHECK)::ObjectSynchronizer
  |   |   |   |-if (UseBiasedLocking)
  |   |   |   |   |-if (!SafepointSynchronize::is_at_safepoint())
  |   |   |   |   |   |-cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD)
  |   |   |   |   |   |   |-update_heuristics(obj(), attempt_rebias)
  |   |   |   |   |   |   |-if (heuristics == HR_SINGLE_REVOKE)
  |   |   |   |   |   |   |   |-if (mark->biased_locker() == THREAD && prototype_header->bias_epoch() == mark->bias_epoch())
  |   |   |   |   |   |   |   |-else  // 因为当前线程不是偏向线程,所以由 VMThread 执行撤销 revoke,最终会在 safepoint 调用 revoke_bias 方法撤销偏向
  |   |   |   |   |   |   |   |   |-VM_RevokeBias revoke(&obj, (JavaThread*) THREAD)
  |   |   |   |   |   |   |   |   |-VMThread::execute(&revoke)
  |   |   |   |-slow_enter(obj, lock, THREAD)::ObjectSynchronizer // 所以最终还是走到 slow_enter 方法
  |   |   |   |   | // 走到这里说明发生轻量级锁竞争或者是重量级锁,需要膨胀为重量级锁,膨胀完再调用 ObjectMonitor::enter 方法
  |   |   |   |   |-ObjectSynchronizer::inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD);

// case 2
CASE(_monitorexit)::bytecodeInterpreter
  |-monitorexit(THREAD, most_recent)::InterpreterRuntime
  |   |-slow_exit(h_obj(), elem->lock(), thread)::ObjectSynchronizer
  |   |   |-fast_exit(object, lock, THREAD)::ObjectSynchronizer
  |   |   |   | // 走到这里说明符合任一条件,case1: 当前是「重量级锁」 case2: 是轻量级锁,但 CAS 失败 (即解锁时发生竞争)
  |   |   |   | // 需要膨胀为重量级锁,膨胀完再调用 ObjectMonitor::exit 方法
  |   |   |   |-ObjectSynchronizer::inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD)

ObjectSynchronizer::inflate 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/synchronizer.cpp#L1249-L1447

// The mark can be in one of the following states:            Mark Word可能有以下几种状态:
// *  Inflated     - just return                              *  Inflated (膨胀完成)     - 这种状态说明该锁已经是重量级锁了,不需要膨胀,直接返回
// *  Stack-locked - coerce it to inflated                    *  Stack-locked (轻量级锁) - 需要执行膨胀操作
// *  INFLATING    - busy wait for conversion to complete     *  INFLATING (膨胀中)     - 正在膨胀中
// *  Neutral      - aggressively inflate the object.         *  Neutral (无锁)        - 强制执行膨胀操作
// *  BIASED       - Illegal.  We should never see this       *  BIASED (偏向锁)       - 出现偏向锁是不合理的,需要抛出异常
ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self,
                                                  oop object,
                                                  const InflateCause cause) {
  // 校验当前不能是 safepoint 点
  assert (Universe::verify_in_progress() ||
          !SafepointSynchronize::is_at_safepoint(), "invariant") ;

  EventJavaMonitorInflate event;

  for (;;) { // 无限循环
      const markOop mark = object->mark() ;
      // 校验当前锁对象不能是偏向模式,否则报错
      assert (!mark->has_bias_pattern(), "invariant") ; 

      // CASE: inflated
      // 锁对象的 markword 是重量级状态 (10),直接返回已经创建好的 ObjectMonitor 对象
      if (mark->has_monitor()) {
          ObjectMonitor * inf = mark->monitor() ;
          assert (inf->header()->is_neutral(), "invariant");
          assert (inf->object() == object, "invariant") ;
          assert (ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
          return inf ;
      }

      // CASE: inflation in progress - inflating over a stack-lock.
      // 锁对象的 markword 是「正在膨胀中」,说明另外一个线程正在进行锁膨胀,continue 继续下次循环
      if (mark == markOopDesc::INFLATING()) {
         TEVENT (Inflate: spin while INFLATING) ;
        // 在该方法中会进行 spin/yield/park 等操作完成自旋动作 
         ReadStableMark(object) ;
         continue ;
      }

      // CASE: stack-locked
      // 当前是轻量级锁状态,先分配一个 ObjectMonitor 对象,并初始化值
      if (mark->has_locker()) {
          // omAlloc 用来分配 ObjectMonitor,在每个线程中有一个 omFreeList 用来保存 ObjectMonitor
          // 1. 分配 ObjectMonitor 时,会先从该线程的 omFreeList 获取一个未被使用的 ObjectMonitor
          // 2. 如果线程没有空闲 ObjectMonitor,则从 JVM 全局的 gFreeList 中分配一批 ObjectMonitor 到该线程的 omFreeList 中
          // 3. 如果前两者都为空,则重新分配一组监视器,并挂载到全局队列 gFreeList 末尾,继续执行第 1 点
          ObjectMonitor * m = omAlloc (Self) ;
          // Optimistically prepare the objectmonitor - anticipate successful CAS
          // We do this before the CAS in order to minimize the length of time
          // in which INFLATING appears in the mark.
          m->Recycle(); // 对分配的监视器对象执行复位操作
          m->_Responsible  = NULL ; // 对分配的监视器对象的 _Responsible 置为 NULl
          m->OwnerIsThread = 0 ; // 对分配的监视器对象的 OwnerIsThread 置为 0
          m->_recursions   = 0 ; // 对分配的监视器对象的 _recursions 重入次数置为 0
          // 设置自旋获取重量级锁的次数 默认 5000
          m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;   // Consider: maintain by type/class

          // CAS 将锁对象的 markword 设置为 INFLATING (0) 状态 
          markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
          // 尝试失败(说明另一个线程也分配了一个 ObjectMonior 并竞争成功)
          if (cmp != mark) {
             // 释放 ObjectMonitor 对象,调用 omRelease,需要把当前 ObjectMonitor 从 omInUseList 离队并加入到 omFreeList 的队首,并 continue 继续下次循环
             omRelease (Self, m, true) ;
             continue ;       // Interference -- just retry
          }

          markOop dmw = mark->displaced_mark_helper() ;
          assert (dmw->is_neutral(), "invariant") ;

          // Setup monitor fields to proper values -- prepare the monitor
          // 取出轻量级锁对应的 LockRecord 的 displaced_header (001) markword,设置到 ObjectMonitor 的 _header
          m->set_header(dmw) ;

          // 设置 ObjectMonitor 的 _owner 为锁对象 Lock Record 指针地址 (这里是拥有轻量级锁的线程中的内存地址)
          // 因为轻量级锁在退出同步代码块之后,会释放锁变成无锁状态。如果当前是轻量级锁,说明有已经获取到锁的线程正在执行同步代码块
          m->set_owner(mark->locker());
          // 设置 ObjectMonitor 的 _object 为当前锁对象
          m->set_object(object);
          guarantee (object->mark() == markOopDesc::INFLATING(), "invariant") ;
          // 将锁对象的 markword 设置成当前监视器(ObjectMonitor)的地址,顺便最后两位置为 10 (重量级锁)
          object->release_set_mark(markOopDesc::encode(m));

          if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
          TEVENT(Inflate: overwrite stacklock) ;
          if (TraceMonitorInflation) {
            if (object->is_instance()) {
              ResourceMark rm;
              tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
                (void *) object, (intptr_t) object->mark(),
                object->klass()->external_name());
            }
          }
          if (event.should_commit()) {
            post_monitor_inflate_event(&event, object, cause);
          }
          // 返回 ObjectMonitor 对象 m
          return m ;
      }

      // CASE: neutral
      // 剩下就是无锁情况
      assert (mark->is_neutral(), "invariant"); // 校验当前锁对象的mark是无锁状态(最后三位 001)
      // 分配一个 ObjectMonitor 对象,并初始化值
      ObjectMonitor * m = omAlloc (Self) ;
      // prepare m for installation - set monitor to initial state
      m->Recycle(); // 对分配的 ObjectMonitor 对象执行复位操作
      m->set_header(mark); // 将 ObjectMonitor 对象的 _header 置成锁对象的 markword
      // 无锁就是当前线程自己加锁了,所以不要设置 owner,只要修改 OwnerIsThread 标记为 1 就行
      m->set_owner(NULL); // 将 ObjectMonitor 对象的 _owner 置为 NULL
      m->set_object(object); // 将 ObjectMonitor 对象的 _object 置为当前锁对象
      m->OwnerIsThread = 1 ; // 将 ObjectMonitor 对象的 OwnerIsThread 置为 1
      m->_recursions   = 0 ; // 将 ObjectMonitor 对象的 _recursions 重入次数为 0
      m->_Responsible  = NULL ; // 将 ObjectMonitor 对象的 
      // 设置自旋获取重量级锁的次数 默认 5000
      m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;       // consider: keep metastats by type/class

      // CAS 将 ObjectMonitor 对象的 markword 设置成 当前监视器(ObjectMonitor)的地址,顺便最后两位置为 10 (重量级锁)
      if (Atomic::cmpxchg_ptr (markOopDesc::encode(m), object->mark_addr(), mark) != mark) {
          // 失败,清空设置,释放 ObjectMonitor 对象,调用 omRelease,需要把当前 ObjectMonitor 从 omInUseList 离队并加入到 omFreeList 的队首,并 continue 继续下次循环
          m->set_object (NULL) ;
          m->set_owner  (NULL) ;
          m->OwnerIsThread = 0 ;
          m->Recycle() ;
          omRelease (Self, m, true) ;
          m = NULL ;
          continue ;
      }

      if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
      TEVENT(Inflate: overwrite neutral) ;
      if (TraceMonitorInflation) {
        if (object->is_instance()) {
          ResourceMark rm;
          tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
            (void *) object, (intptr_t) object->mark(),
            object->klass()->external_name());
        }
      }
      if (event.should_commit()) {
        post_monitor_inflate_event(&event, object, cause);
      }
      //成功,返回 ObjectMonitor 对象 
      return m ;
  }
}
  1. 已经是重量级状态,说明膨胀已经完成,返回并继续执行ObjectMonitor::enter方法
  2. 如果是轻量级锁则需要进行膨胀操作
  3. 如果是膨胀中状态,则进行忙等待
  4. 如果是无锁状态则需要进行膨胀操作

    获取重量级锁

CASE(_monitorenter)::bytecodeInterpreter
  |-monitorenter(thread, elem)::InterpreterRuntime
  |   |-if (UseBiasedLocking)
  |   |   |-fast_enter(h_obj, elem->lock(), true, CHECK)::ObjectSynchronizer
  |   |   |   |-if (UseBiasedLocking)
  |   |   |   |   |-if (!SafepointSynchronize::is_at_safepoint())
  |   |   |   |   |   |-cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD)
  |   |   |   |   |   |   |-update_heuristics(obj(), attempt_rebias)
  |   |   |   |   |   |   |-if (heuristics == HR_SINGLE_REVOKE)
  |   |   |   |   |   |   |   |-if (mark->biased_locker() == THREAD && prototype_header->bias_epoch() == mark->bias_epoch())
  |   |   |   |   |   |   |   |-else  // 因为当前线程不是偏向线程,所以由 VMThread 执行撤销 revoke,最终会在 safepoint 调用 revoke_bias 方法撤销偏向
  |   |   |   |   |   |   |   |   |-VM_RevokeBias revoke(&obj, (JavaThread*) THREAD); VMThread::execute(&revoke)
  |   |   |   |-slow_enter(obj, lock, THREAD)::ObjectSynchronizer // 所以最终还是走到 slow_enter 方法
  |   |   |   |   | // 走到这里说明发生轻量级锁竞争或者是重量级锁,需要膨胀为重量级锁,膨胀完再调用 ObjectMonitor::enter 方法
  |   |   |   |   |-ObjectSynchronizer::inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD) 
  |   |   |   |   |   |-ObjectMonitor::enter(THREAD)
  |   |   |   |   |   |   |-if (Knob_SpinEarly && TrySpin(Self) > 0) // TrySpin: ObjectMonitor::TrySpin_VaryDuration
  |   |   |   |   |   |   |                         |-ObjectMonitor::TryLock(Self)
  |   |   |   |   |   |   |-for (;;)
  |   |   |   |   |   |   |   |-ObjectMonitor::EnterI(THREAD)
  |   |   |   |   |   |   |   |   |-ObjectMonitor::TryLock(Self)
  |   |   |   |   |   |   |   |   |-for (;;) // 循环 CAS 将 ObjectWaiter node 设置到 _cxq 队列头
  |   |   |   |   |   |   |   |   |   |-if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break;
  |   |   |   |   |   |   |   |   |   |-if (TrySpin(Self) > 0) return;
  |   |   |   |   |   |   |   |   |-for (;;) // 循环,先尝试获取锁,失败挂起 (park) 自己,当获取锁的线程释放锁时会唤醒 (unpark) _EntryList 或 _cxq 的节点,继续竞争锁
  |   |   |   |   |   |   |   |   |   |-if (TryLock (Self) > 0) break;
  |   |   |   |   |   |   |   |   |   |-if (_Responsible == Self || (SyncFlags & 1))
  |   |   |   |   |   |   |   |   |   |   |-Self->_ParkEvent->park ((jlong) RecheckInterval)
  |   |   |   |   |   |   |   |   |   |-else
  |   |   |   |   |   |   |   |   |   |   |-Self->_ParkEvent->park()
  |   |   |   |   |   |   |   |   |   |-if (TryLock(Self) > 0) break ;
  |   |   |   |   |   |   |   |   |-UnlinkAfterAcquire (Self, &node) // 将封装了当前线程的 ObjectWaiter node 节点从「等待队列 _cxq」或「等待队列 _EntryList」中移除

ObjectMonitor::enter 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L321-L483

void ATTR ObjectMonitor::enter(TRAPS) {
  Thread * const Self = THREAD ;
  void * cur ;

  // CAS 修改 ObjectMonitor 对象的 _owner 为当前线程,_owner 为 NULL 代表当前 ObjectMonitor 锁是无人竞争,可获取
  cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
  if (cur == NULL) { // 返回值 cur 是 NULL,CAS 成功,说明获取重量级锁成功,直接返回
     assert (_recursions == 0   , "invariant") ; // 校验重入次数是否 0
     assert (_owner      == Self, "invariant") ; // 校验 monitor 对象的 _owner 是否为当前线程
     return ;
  }

  if (cur == Self) { // // 返回值 cur 是当前线程,CAS 失败,但是 monitor 的 _owner 的值就是当前线程,说明是重量级锁重入,直接返回
     _recursions ++ ; // 重入次数 +1
     return ;
  }

  // 返回值 cur 地址是在当前线程栈 Lock Record 地址范围中的
  // 说明是当前线程持有「轻量级锁」,且 monitor 对象是竞争线程初始化,说明持有轻量级锁线程重入,并发现锁对象的 markword 已经被修改为重量级锁了
  // case1: 当前线程 T1 已经获取到「轻量级锁」(无锁->轻量级锁),之后线程 T2 执行 monitorenter 竞争轻量级锁失败,进行膨胀为重量级锁,
  //        并在初始化 ObjectMonitor 对象的 _owner 为持有轻量级锁的线程 T1 的 Lock Record 指针地址,
  //        刚好初始化完 ObjectMonitor,此时线程 T1 执行内嵌的同步代码块即重入执行 monitorenter 来获取锁,
  //        执行到当前代码,就出现是返回值 cur 地址,是在当前线程栈 Lock Record 地址范围中的
  if (Self->is_lock_owned ((address)cur)) {
    assert (_recursions == 0, "internal state error");
    _recursions = 1 ; // 设置重入次数等于 1
    _owner = Self ; // 修改 ObjectMonitor 对象的 _owner 值由「当前线程的 Lock Record 指针地址」改为「当前线程指针地址」
    OwnerIsThread = 1 ; // 修改 ObjectMonitor 对象的 OwnerIsThread 为 1
    return ; // 直接返回
  }

  // We've encountered genuine contention.
  assert (Self->_Stalled == 0, "invariant") ;
  Self->_Stalled = intptr_t(this) ; // 当前线程的 _Stalled 置为「当前 ObjectMonitor 对象的地址」,表示当前线程在这个对象上停住了

  // 执行到这里说明重量级锁是被其他线程持有,进行尝试「自适应自旋」来获取重量级锁
  if (Knob_SpinEarly && TrySpin (Self) > 0) { // 如果 adaptive spin 获取到重量级锁
     assert (_owner == Self      , "invariant") ;
     assert (_recursions == 0    , "invariant") ;
     assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
     Self->_Stalled = 0 ; // 设置当前线程的 _Stalled 置为 0,标识当前线程没有停住
     return ; // 直接返回
  }

  // 执行到这里,说明获取重量级锁失败,进行一系列检查
  assert (_owner != Self          , "invariant") ; // 检查 ObjectMonitor 对象的 _owner 值,不能是当前线程
  assert (_succ  != Self          , "invariant") ;
  assert (Self->is_Java_thread()  , "invariant") ;
  JavaThread * jt = (JavaThread *) Self ;
  assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
  assert (jt->thread_state() != _thread_blocked   , "invariant") ; // 当前 Java 线程状态不能为 blocked
  assert (this->object() != NULL  , "invariant") ; // 检查 ObjectMonitor 对象的 _object 不能为空 (即是锁对象要存在)
  assert (_count >= 0, "invariant") ;

  Atomic::inc_ptr(&_count); // 自增当前 ObjectMonitor 对象的引用计数 _count,防止在 STW 期间被回收

  JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
  EventJavaMonitorEnter event;
  if (event.should_commit()) {
    event.set_monitorClass(((oop)this->object())->klass());
    event.set_address((uintptr_t)(this->object_addr()));
  }

  { // 修改 Java 层面线程的状态 threadStatus 为 java_lang_Thread::BLOCKED_ON_MONITOR_ENTER
    JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);

    // 修改当前线程的 set_current_pending_monitor 为当前的 ObjectMonitor 对象,表示当前线程 pending 在这个 ObjectMonitor 对象获取重量级锁中
    Self->set_current_pending_monitor(this);

    DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
    if (JvmtiExport::should_post_monitor_contended_enter()) {
      JvmtiExport::post_monitor_contended_enter(jt, this);
    }

    // 修改当前线程对应的操作系统(windows,linux 等)的线程状态为 MONITOR_WAIT
    OSThreadContendState osts(Self->osthread());
    // JVM 层面的线程,修改当前线程状态从 _thread_in_vm 到 _thread_blocked
    ThreadBlockInVM tbivm(jt);

    // TODO-FIXME: change the following for(;;) loop to straight-line code.
    for (;;) { // 无限循环
      jt->set_suspend_equivalent(); // 设置 Java 层面的线程的  _suspend_equivalent 为 true
      // cleared by handle_special_suspend_equivalent_condition()
      // or java_suspend_self()
      // 调用 EnterI 方法来获取重量级锁,获取不到进行阻塞
      EnterI (THREAD) ;

      // 执行到这里说明已经获取重量级锁成功
      if (!ExitSuspendEquivalent(jt)) break ; // 如果在加锁过程中,当前线程没有被外部中断,则跳出循环

      // 执行到这里,说明在加锁过程中,当前线程被外部中断
          _recursions = 0 ; // 设置当前的 ObjectMonitor 对象的重入次数为 0
      _succ = NULL ; // 设置当前的 ObjectMonitor 对象的 _succ 为 null
      exit (false, Self) ; // 执行 ObjectMonitor::exit 释放重量级锁

      jt->java_suspend_self();
    }
    // 执行到这里说明已经获取重量级锁成功,将当前线程的 _current_pending_monitor 置由「当前的 ObjectMonitor 对象」为「NULL」
    Self->set_current_pending_monitor(NULL);
  }

  Atomic::dec_ptr(&_count); // 递减当前 ObjectMonitor 对象的引用计数 _count
  assert (_count >= 0, "invariant") ;
  Self->_Stalled = 0 ; // 设置当前线程的 _Stalled 置为 0,标识当前线程没有停住

  // Must either set _recursions = 0 or ASSERT _recursions == 0.
  assert (_recursions == 0     , "invariant") ;
  assert (_owner == Self       , "invariant") ;
  assert (_succ  != Self       , "invariant") ;
  assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;

  DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
  if (JvmtiExport::should_post_monitor_contended_entered()) {
    JvmtiExport::post_monitor_contended_entered(jt, this);
  }

  if (event.should_commit()) {
    event.set_previousOwner((uintptr_t)_previous_owner_tid);
    event.commit();
  }

  if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) {
     ObjectMonitor::_sync_ContendedLockAttempts->inc() ;
  }
}

ObjectMonitor::TrySpin_VaryDuration 方法 | 自适应自旋

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L2021-L2244

int ObjectMonitor::TrySpin_VaryDuration (Thread * Self) {
    int ctr = Knob_FixedSpin ; // Knob_FixedSpin = 0 固定的自旋次数,不作为真正的使用,仅用来对比
    if (ctr != 0) {
        // //固定自旋一定的测试,由于 Knob_FixedSpin 为 0,所以这段代码在不参与实际运行,仅作为对比测试
        while (--ctr >= 0) {
            // TryLock 方法尝试获取重量级锁,成功直接 return 1,表示自旋获取重量级锁成功
            // * 如果 _owner 不为空,返回 0,表示已经被别的线程持有
            // * 如果 _owner 为空,进行 cas 成功返回 1,表示获取到锁,接着退出该方法
            // * 如果 _owner 为空,进行 cas 失败返回 -1,说明其他线程刚刚 CAS 成功设置获取到「重量级锁」,此时没有必要进行自旋
            if (TryLock (Self) > 0) return 1 ; 
            SpinPause () ; // 以 poll(NULL, 0, 100); 的方式暂停当前线程
        }
        return 0 ;
    }

    // Knob_PreSpin = 10 这里时预先自旋的次数,在真正消耗 _SpinDuration 之前,会进行自旋的次数。20-100 likely better
    // _SpinDuration 这个表示自旋的时间,在初始化时会设置为和 Knob_SpinLimit 一样的值 5000,这个值并不是固定的,会根据最近自旋的成功率而进行上下的浮动
    for (ctr = Knob_PreSpin + 1; --ctr >= 0 ; ) {
      // TryLock 方法尝试获取重量级锁
      // * 如果 _owner 不为空,返回 0,表示已经被别的线程持有
      // * 如果 _owner 为空,进行 cas 成功返回 1,表示获取到锁,接着退出该方法
      // * 如果 _owner 为空,进行 cas 失败返回 -1,说明其他线程刚刚 CAS 成功设置获取到「重量级锁」,此时没有必要进行自旋
      if (TryLock(Self) > 0) { // 成功获取重量级锁,成功直接 return 1,失败继续下一轮循环
        int x = _SpinDuration ;
        // Knob_SpinLimit = 5_000,自旋次数的上限值
        if (x < Knob_SpinLimit) {
           // 自旋成功 _SpinDuration 如果低于最低值,会被重新赋予最低值 Knob_Poverty 默认值为 1000
           if (x < Knob_Poverty) x = Knob_Poverty ;
           // 自旋成功 _SpinDuration 会相应的进行增加,Knob_BonusB = 100 (自旋成功后会增加一定的时间 spin success bonus)
           _SpinDuration = x + Knob_BonusB ;
        }
        return 1 ; // 成功直接 return 1,表示自旋获取重量级锁成功
      }
      SpinPause () ; // 以 poll(NULL, 0, 100); 的方式暂停当前线程
    }

    ctr = _SpinDuration  ;
    // 这里确保 _SpinDuration 不是小于 0 的,Knob_SpinBase = 0 (Floor AKA SpinMin)
    if (ctr < Knob_SpinBase) ctr = Knob_SpinBase ;
    if (ctr <= 0) return 0 ; // _SpinDuration 小于等于 0,直接 return 0,表示自旋获取重量级锁失败

    if (Knob_SuccRestrict && _succ != NULL) return 0 ;
    // NotRunnable 用于判断获取到锁的线程是否处于运行状态,因为只有正在运行的线程在执行完之后才会释放锁
    // 如果当前线程是阻塞的线程那么就没有必要自旋等待锁,这里获取到线程的状态可能时错误的,因为获取到锁的线程可能已经死亡,返回值仅作为参考
    if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) {
       TEVENT (Spin abort - notrunnable [TOP]);
       return 0 ; // 直接 return 0,表示自旋获取重量级锁失败
    }

    int MaxSpin = Knob_MaxSpinners ;
    if (MaxSpin >= 0) {
       // Knob_MaxSpinners 为 CPU 的数量,如果正在自旋的数量大于 CPU 的数量,说明太多尝试自旋的线程
       if (_Spinner > MaxSpin) {
          TEVENT (Spin abort -- too many spinners) ;
          return 0 ; // 直接 return 0,表示自旋获取重量级锁失败
       }
       // Slighty racy, but benign ...
       Adjust (&_Spinner, 1) ;
    }

    int hits    = 0 ;
    int msk     = 0 ;
    int caspty  = Knob_CASPenalty ;
    int oxpty   = Knob_OXPenalty ;
    int sss     = Knob_SpinSetSucc ;
    if (sss && _succ == NULL ) _succ = Self ;
    Thread * prv = NULL ;

    while (--ctr >= 0) {
      if ((ctr & 0xFF) == 0) {
         // 如果不是在安全点执行该操作,这个操作会被中止
         if (SafepointSynchronize::do_call_back()) {
            TEVENT (Spin: safepoint) ;
            goto Abort ;           // abrupt spin egress
         }
         if (Knob_UsePause & 1) SpinPause () ;

         int (*scb)(intptr_t,int) = SpinCallbackFunction ;
         if (hits > 50 && scb != NULL) {
            int abend = (*scb)(SpinCallbackArgument, 0) ;
         }
      }

      if (Knob_UsePause & 2) SpinPause() ;
      if (ctr & msk) continue ;
      ++hits ;
      if ((hits & 0xF) == 0) {
        // The 0xF, above, corresponds to the exponent.
        // Consider: (msk+1)|msk
        msk = ((msk << 2)|3) & BackOffMask ;
      }

      // 这里是获取锁的操作,如果当前 ObjectMonitor 对象的 _owner 为 NULL 就会尝试 CAS 获取「重量级锁」
      Thread * ox = (Thread *) _owner ;
      if (ox == NULL) {
         ox = (Thread *) Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
         if (ox == NULL) { // 成功获取重量级锁
            // The CAS succeeded -- this thread acquired ownership
            // Take care of some bookkeeping to exit spin state.
            if (sss && _succ == Self) {
               _succ = NULL ;
            }
            if (MaxSpin > 0) Adjust (&_Spinner, -1) ;

            int x = _SpinDuration ;
            if (x < Knob_SpinLimit) {
                // 自旋成功 _SpinDuration 如果低于最低值,会被重新赋予最低值 Knob_Poverty 默认值为 1000
                if (x < Knob_Poverty) x = Knob_Poverty ;
                // 自旋成功 _SpinDuration 会相应的进行增加,Knob_BonusB = 100 (自旋成功后会增加一定的时间 spin success bonus)
                _SpinDuration = x + Knob_Bonus ;
            }
            return 1 ; // 成功直接 return 1,表示自旋获取重量级锁成功
         }

         // 获取重量级锁失败,会根据情况是重试还是退出,如果失败的概率很高,就会直接退出
         prv = ox ;
         TEVENT (Spin: cas failed) ;
         if (caspty == -2) break ;
         if (caspty == -1) goto Abort ;
         ctr -= caspty ;
         continue ;
      }

      // Did lock ownership change hands ?
      if (ox != prv && prv != NULL ) {
          TEVENT (spin: Owner changed)
          if (oxpty == -2) break ;
          if (oxpty == -1) goto Abort ;
          ctr -= oxpty ;
      }
      prv = ox ;

      if (Knob_OState && NotRunnable (Self, ox)) {
         TEVENT (Spin abort - notrunnable);
         goto Abort ;
      }
      if (sss && _succ == NULL ) _succ = Self ;
   }

   // 自旋失败,则会进行相应的惩罚
   TEVENT (Spin failure) ;
   {
     int x = _SpinDuration ;
     if (x > 0) {
        x -= Knob_Penalty ;
        if (x < 0) x = 0 ;
        _SpinDuration = x ;
     }
   }

 Abort:
   if (MaxSpin >= 0) Adjust (&_Spinner, -1) ;
   if (sss && _succ == Self) {
      _succ = NULL ;
      OrderAccess::fence() ;
      if (TryLock(Self) > 0) return 1 ;
   }
   return 0 ;
}

ObjectMonitor::TryLock 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L489-L506

int ObjectMonitor::TryLock (Thread * Self) {
   for (;;) { // 无限循环
      void * own = _owner ;
      // 当前 ObjectMonitor 对象的 _owner 不为 NULL,说明「重量级锁」已被其他线程持有,返回 0
      if (own != NULL) return 0 ;

      // 当前 ObjectMonitor 对象的 _owner 为 NULL,说明重量级锁可以竞争获取

      // CAS 操作以「NULL」作为比较值,以「当前线程指针地址」作为替换值,进行设置「当前 ObjectMonitor 对象的 _owner」内存值
      // CAS 成功,说明获取到「重量级锁」,返回 1
      if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
         // Either guarantee _recursions == 0 or set _recursions = 0.
         assert (_recursions == 0, "invariant") ;
         assert (_owner == Self, "invariant") ;
         // CONSIDER: set or assert that OwnerIsThread == 1
         return 1 ;
      }
      // The lock had been free momentarily, but we lost the race to the lock.
      // Interference -- the CAS failed.
      // We can either return -1 or retry.
      // Retry doesn't make as much sense because the lock was just acquired.
      // CAS 失败,说明其他线程刚刚 CAS 成功设置获取到「重量级锁」,此时没有必要进行自旋,直接返回 -1
      if (true) return -1 ;
   }
}

ObjectMonitor:: EnterI 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L508-L747

void ATTR ObjectMonitor::EnterI (TRAPS) {
    Thread * Self = THREAD ;
    assert (Self->is_Java_thread(), "invariant") ;
    assert (((JavaThread *) Self)->thread_state() == _thread_blocked   , "invariant") ; // 校验当前线程的状态是 _thread_blocked

    // Try the lock - TATAS
    // TryLock 方法尝试获取重量级锁
    // * 如果 _owner 不为空,返回 0,表示已经被别的线程持有
    // * 如果 _owner 为空,进行 cas 成功返回 1,表示获取到锁,接着退出该方法
    // * 如果 _owner 为空,进行 cas 失败返回 -1,说明其他线程刚刚 CAS 成功设置获取到「重量级锁」,此时没有必要进行自旋
    if (TryLock (Self) > 0) { // 获取到重量级锁
        assert (_succ != Self              , "invariant") ;
        assert (_owner == Self             , "invariant") ;
        assert (_Responsible != Self       , "invariant") ;
        return ; // 直接返回,结束当前方法
    }

    DeferredInitialize () ; // 调用 DeferredInitialize,该方法主要是加载 Knob_** 相关的初始化配置,ObjectMonitor 全局执行一次

    // 尝试「自适应自旋」来获取重量级锁
    if (TrySpin (Self) > 0) { // 获取到重量级锁
        assert (_owner == Self        , "invariant") ;
        assert (_succ != Self         , "invariant") ;
        assert (_Responsible != Self  , "invariant") ;
        return ; // 直接返回,结束当前方法
    }

    // The Spin failed -- Enqueue and park the thread ...
    assert (_succ  != Self            , "invariant") ;
    assert (_owner != Self            , "invariant") ;
    assert (_Responsible != Self      , "invariant") ;

    // 执行到这里说明还是获取重量级锁失败,接下里就将当前线程封装成 ObjectWaiter 节点,放到等待 (阻塞) _cxq 队列,并挂起当前线程
    ObjectWaiter node(Self) ; // 当前线程封装成 ObjectWaiter 的节点并记做 node
    Self->_ParkEvent->reset() ; // 对当前线程的 _ParkEvent 进行复位
    node._prev   = (ObjectWaiter *) 0xBAD ; // node 节点 (ObjectWaiter) 的 _prev 设置为 0xBAD
    node.TState  = ObjectWaiter::TS_CXQ ; // node 节点 (ObjectWaiter) 的 TState 设置为 ObjectWaiter::TS_CXQ

    ObjectWaiter * nxt ;
    for (;;) { // 无限循环
        // 「等待(阻塞)队列 _cxq」是一个单向链表
        // 对封装了当前线程的 ObjectWaiter node 节点的 _next 和 nxt 设置为「等待(阻塞)队列 _cxq」
        node._next = nxt = _cxq ;
        // CAS 尝试把封装了当前线程的 ObjectWaiter node 节点添加到「等待(阻塞)队列 _cxq」的队首
        // CAS 成功,跳出循环
        if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;

        // CAS 失败,再次调用 TryLock 方法尝试获取重量级锁
        // TryLock 成功,直接返回退出方法,失败,进行下一轮循环,继续竞争「等待(阻塞)队列 _cxq」队首
        if (TryLock (Self) > 0) { 
            assert (_succ != Self         , "invariant") ;
            assert (_owner == Self        , "invariant") ;
            assert (_Responsible != Self  , "invariant") ;
            return ;
        }
    }

    // 「等待(阻塞)队列 _EntryList」是一个双向链表,节点也是 ObjectWaiter 
    // SyncFlags 默认为 0,且「等待(阻塞)队列 _cxq」为 NULL 且「等待(阻塞)队列 _EntryList」也为 NULL
    // 这段代码是设置一个负责人,如果所有的线程都阻塞了,那么谁来唤醒呢?
    // * 负责人在进行阻塞时,只会阻塞有限的一段时间,就会被唤醒,再次尝试获取锁
    // * 如果这个负责人成功获取到了锁,那么 Responsible 会被置为空
    // * 新的负责人会由新来的线程担任,这时为了防止队列中的线程,没有线程"醒来"而出现的"搁浅"
    // * 那么,如果没有新的线程来并不是说这个队列就不会有线程被唤醒
    // * 获取到锁的线程在释放锁的时候,就会唤醒它的继承者 _succ 线程
    if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
        // Try to assume the role of responsible thread for the monitor.
        // CONSIDER:  ST vs CAS vs { if (Responsible==null) Responsible=Self }
        // CAS 尝试把 _Responsible 置为当前线程,不考虑是否成功
        Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
    }

    TEVENT (Inflated enter - Contention) ;
    int nWakeups = 0 ;
    int RecheckInterval = 1 ;

    for (;;) { // 无限循环

        if (TryLock (Self) > 0) break ; // 调用 TryLock 方法尝试获取重量级锁,成功退出循环
        assert (_owner != Self, "invariant") ;

        if ((SyncFlags & 2) && _Responsible == NULL) {
           Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ; // 设置负责人
        }

        // park self
        // 如果当前线程是负责人,当前线程挂起一段时间,不是一直挂起
        if (_Responsible == Self || (SyncFlags & 1)) {
            TEVENT (Inflated enter - park TIMED) ;
            // 当前线程是 _Responsible 时,调用的是当前线程的 _ParkEvent 的带时间参数的 park 函数,挂起线程
            Self->_ParkEvent->park ((jlong) RecheckInterval) ;
            // Increase the RecheckInterval, but clamp the value.
            RecheckInterval *= 8 ;
            if (RecheckInterval > 1000) RecheckInterval = 1000 ;
        } else {
            TEVENT (Inflated enter - park UNTIMED) ;
            // 非负责人线程,调用当前线程的 _ParkEvent 的 park 函数,挂起线程
            Self->_ParkEvent->park() ;
        }

        // 执行到这里,说明可能是负责人定时被唤醒,也可能普通线程被唤醒,也可能是虚假唤醒
        // 调用 TryLock 方法尝试获取重量级锁,成功退出循环
        if (TryLock(Self) > 0) break ;

        TEVENT (Inflated enter - Futile wakeup) ;
        if (ObjectMonitor::_sync_FutileWakeups != NULL) {
           ObjectMonitor::_sync_FutileWakeups->inc() ;
        }
        ++ nWakeups ;

        // 再尝试「自适应自锁」来获取重量级锁,获取成功,退出循环
        if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;

        if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {
           Self->_ParkEvent->reset() ;
           OrderAccess::fence() ;
        }
        // 如果不是虚假唤醒,那么一般 succ == Self,如果 _succ 是当前线程,则将其置为 NULL
        if (_succ == Self) _succ = NULL ;

        // Invariant: after clearing _succ a thread *must* retry _owner before parking.
        // 内存屏障,防止指令重排序
        OrderAccess::fence() ;
        // 继续下一轮循环,竞争获取重量级锁,如果获取失败,将当前线程挂起来
    }

    // 执行到这里,说明已经获取到「重量级锁」
    assert (_owner == Self      , "invariant") ;
    assert (object() != NULL    , "invariant") ;
    // 将封装了当前线程的 ObjectWaiter node 节点从「等待(阻塞)队列 _cxq」或「等待(阻塞)队列 _EntryList」中移除
    UnlinkAfterAcquire (Self, &node) ;
    // 如果不是虚假唤醒,那么一般 succ == Self,如果 _succ 是当前线程,则将其置为 NULL
    if (_succ == Self) _succ = NULL ;

    assert (_succ != Self, "invariant") ;
    if (_Responsible == Self) {
        _Responsible = NULL ;
        OrderAccess::fence(); // Dekker pivot-point
    }

    if (SyncFlags & 8) {
       OrderAccess::fence() ;
    }
    // 直接返回,退出当前方法
    return ;
}

ObjectWaiter 定义

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.hpp#L38-L56

class ObjectWaiter : public StackObj {
 public:
  enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
  enum Sorted  { PREPEND, APPEND, SORTED } ;
  ObjectWaiter * volatile _next;
  ObjectWaiter * volatile _prev;
  Thread*       _thread;
  jlong         _notifier_tid;
  ParkEvent *   _event;
  volatile int  _notified ;
  volatile TStates TState ;
  Sorted        _Sorted ;           // List placement disposition
  bool          _active ;           // Contention monitoring is enabled
 public:
  ObjectWaiter(Thread* thread);

  void wait_reenter_begin(ObjectMonitor *mon);
  void wait_reenter_end(ObjectMonitor *mon);
};

ObjectMonitor::UnlinkAfterAcquire 方法 | 将封装了当前线程的 ObjectWaiter node 节点从「等待队列 _cxq」或「等待队列 _EntryList」中移除

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L848-L909

void ObjectMonitor::UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode)
{
    assert (_owner == Self, "invariant") ;
    assert (SelfNode->_thread == Self, "invariant") ;

    // 默认配置下,_cxq 链表中的节点会被转移到 _EntryList (双链表) 队列中,状态就置为 TS_ENTER
    // 正常情况走此分支,将封装了当前线程的 ObjectWaiter SelfNode 节点从 _EntryList 队列中移除
    // 因为 _EntryList 是不会与其他线程进行竞争的,所以可以直接移除 SelfNode
    if (SelfNode->TState == ObjectWaiter::TS_ENTER) {
        ObjectWaiter * nxt = SelfNode->_next ; // 获取 SelfNode 的 _next 节点
        ObjectWaiter * prv = SelfNode->_prev ; // 获取 SelfNode 的 _prev 节点
        // SelfNode 从双链表中移除
        if (nxt != NULL) nxt->_prev = prv ; // SelfNode _next 节点不为空,则将 _next 节点断开 SelfNode,连接 SelfNode 的前一个节点
        if (prv != NULL) prv->_next = nxt ; // SelfNode _prev 节点不为空,则将 _prv 节点断开 SelfNode,连接 SelfNode 的下一个节点
        // 如果 SelfNode 是 _EntryList 的头节点,则更新 _EntryList 的头节点为 SelfNode->_next
        if (SelfNode == _EntryList ) _EntryList = nxt ;
        assert (nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant") ;
        assert (prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant") ;
        TEVENT (Unlink from EntryList) ;
    } else {
        // 执行到这里,说明 SelfNode 在 _cxq 单链表中
        // _cxq 单链表队列是可能发生多线程竞争的,因为每个线程竞争重量级锁失败,在将自己 park 起来,
        // 之前都会先将 ObjectWaiter node CAS 尝试插入到 _cxq 队头
        guarantee (SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant") ;
        // 获取 _cxq 队列头节点 (快照,有可能其他线程进行 CAS 将 node 插入 _cxq 队列头)
        ObjectWaiter * v = _cxq ;
        assert (v != NULL, "invariant") ;
        // case 1: 队列头节点 (快照) 不等于 SelfNode 
        // case 2: 队列头节点 (快照) 是 SelfNode,但是尝试 CAS 将 SelfNode 的下一个节点修改为 _cxq 队列的头节点失败 (说明有其他线程竞争 _cxq 队列)
        if (v != SelfNode || Atomic::cmpxchg_ptr (SelfNode->_next, &_cxq, v) != v) {
            // 队列头节点是 SelfNode,但是 CAS 失败
            if (v == SelfNode) {
                assert (_cxq != v, "invariant") ;
                // 重新获取 _cxq 队列头节点 (也是快照)
                v = _cxq ;          // CAS above failed - start scan at head of list
            }
            ObjectWaiter * p ;
            ObjectWaiter * q = NULL ;
            // 从 _cxq 队列头节点,开始遍历链表,直到找到 SelfNode 节点,退出遍历链表
            for (p = v ; p != NULL && p != SelfNode; p = p->_next) {
                q = p ;
                assert (p->TState == ObjectWaiter::TS_CXQ, "invariant") ;
            }
            assert (v != SelfNode,  "invariant") ;
            assert (p == SelfNode,  "Node not found on cxq") ;
            assert (p != _cxq,      "invariant") ;
            assert (q != NULL,      "invariant") ;
            assert (q->_next == p,  "invariant") ;
            // p 即是在 _cxq 中的 SelfNode 节点且不是队头节点
            // q 即是 p 的上一个节点
            // 从 _cxq 移除 p 节点即 SelfNode 节点
            q->_next = p->_next ;
        }
        TEVENT (Unlink from cxq) ;
    }

    SelfNode->_prev  = (ObjectWaiter *) 0xBAD ; // 将已被移除的 SelfNode 的 _prev 设为 0xBAD
    SelfNode->_next  = (ObjectWaiter *) 0xBAD ; // 将已被移除的 SelfNode 的 _next 设为 0xBAD
    SelfNode->TState = ObjectWaiter::TS_RUN ; // 将 SelfNode 的状态设为 TS_RUN
}

释放重量级锁

CASE(_monitorexit)::bytecodeInterpreter
  |-monitorexit(THREAD, most_recent)::InterpreterRuntime
  |   |-slow_exit(h_obj(), elem->lock(), thread)::ObjectSynchronizer
  |   |   |-fast_exit(object, lock, THREAD)::ObjectSynchronizer
  |   |   |   |  // 需要膨胀为重量级锁 (前提是未膨胀过即未创建 ObjectMonitor 对象),再调用 ObjectMonitor::exit 方法
  |   |   |   |-ObjectSynchronizer::inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD)
  |   |   |   |   |-ObjectMonitor::exit(true, THREAD)
  |   |   |   |   |   |-if (THREAD != _owner & !THREAD->is_lock_owned((address) _owner)) // Monitor 对象 _owner 既不是当前线程且当前线程也不是持有过轻量级锁,直接退出
  |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |-if (_recursions != 0) // 重量级锁重入,递减重入次数
  |   |   |   |   |   |   |-_recursions--;
  |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |-for (;;)
  |   |   |   |   |   |   |-if (Knob_ExitPolicy == 0) // 默认为 0
  |   |   |   |   |   |   |   | // 调用操作系统相关的 OrderAccess::release_store_ptr 将当前 ObjectMonitor 对象的 _owner 设置为 NULL,即释放「重量级锁锁」
  |   |   |   |   |   |   |   |-OrderAccess::release_store_ptr (&_owner, NULL)
  |   |   |   |   |   |   |   | // 「等待队列 _EntryList」和「等待队列 _cxq」都是空队列,或者当前 ObjectMonitor 对象的 _succ 后继者已经被指定好,直接退出
  |   |   |   |   |   |   |   |-if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL)
  |   |   |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |   |   | // 设置失败,说明「重量级锁」已被其他线程获取,当前线程不需要做唤醒其他线程工作,直接退出
  |   |   |   |   |   |   |   |-if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL)
  |   |   |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |   |-else // Knob_ExitPolicy != 0 的情况
  |   |   |   |   |   |   |   | // 如果「等待队列 _EntryList」和「等待队列 _cxq」都是空队列,或者当前 ObjectMonitor 对象的 _succ 后继者已经被指定好,表明没有竞争者,或者已经指定好下一个竞争者
  |   |   |   |   |   |   |   |-if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) 
  |   |   |   |   |   |   |   |   | // 调用操作系统相关的 OrderAccess::release_store_ptr 将当前 ObjectMonitor 对象的 _owner 设置为 NULL,即释放「重量级锁锁」
  |   |   |   |   |   |   |   |   |-OrderAccess::release_store_ptr (&_owner, NULL)
  |   |   |   |   |   |   |   |   |-if (_cxq == NULL || _succ != NULL) // 如果“_cxq 为 NULL”或者“当前 ObjectMonitor 对象的 _succ 后继者已经被指定好”,直接退出
  |   |   |   |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |   |   |   | // 设置失败,说明「重量级锁」已被其他线程获取,当前线程不需要做唤醒其他线程工作,直接退出
  |   |   |   |   |   |   |   |   |-if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL)
  |   |   |   |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |   |-int QMode = Knob_QMode // 根据 QMode 的不同会有不同的唤醒策略,Knob_QMode 默认是 0
  |   |   |   |   |   |   |-if (QMode == 2 && _cxq != NULL) // QMode 为 2,表示优先处理 _cxq 队列头节点 (_cxq 等待队列中的 ObjectWaiter 节点的线程优先级更高)
  |   |   |   |   |   |   |   |-ExitEpilog (Self, w) // 执行 ExitEpilog 方法,设置当前 ObjectMonitor 对象的后继者 _succ 为 w 节点的线程,并唤醒 w 节点线程 (Thread->_ParkEvent->unpark())
  |   |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |   |-if (QMode == 3 && _cxq != NULL) // QMode 为 3,表示将 _cxq 的节点批量转移到 _EntryList 队列的「队尾」,w 指向原 _cxq 的队列头节点
  |   |   |   |   |   |   |-if (QMode == 4 && _cxq != NULL) // QMode 为 4,表示将 _cxq 的节点批量转移到 _EntryList 队列的「队首」,w 指向原 _cxq 的队列头节点,同时也是新 _EntryList 队列头节点
  |   |   |   |   |   |   |-w = _EntryList // w 指针指向 _EntryList 队列的头节点
  |   |   |   |   |   |   |-if (w != NULL) // _EntryList 队列不为空,直接唤醒头节点的线程,并直接返回当前方法
  |   |   |   |   |   |   |   |-ExitEpilog (Self, w) // 执行 ExitEpilog 方法,设置当前 ObjectMonitor 对象的后继者 _succ 为 _EntryList 头节点的线程,并唤醒此节点线程 (Thread->_ParkEvent->unpark())
  |   |   |   |   |   |   |   |-return; // 直接退出
  |   |   |   |   |   |   |-w = _cxq // 执行到这里说明 _EntryList 为空,将 w 指针指向 _cxq 队列的头节点 (快照)
  |   |   |   |   |   |   |-if (w == NULL) // _EntryList 和 _cxq 都为空,直接继续下一轮循环
  |   |   |   |   |   |   |   |-continue; // 直接继续下一轮循环
  |   |   |   |   |   |   | // 执行到这里说明 _EntryList 队列为空,但 _cxq 队列由不为空设置为空,w 指针指向「已脱离的 _cxq 队列的链表」的头节点
  |   |   |   |   |   |   |-if (QMode == 1) // QMode 为 1,表示将「已脱离的 _cxq 队列的链表」,进行逆序,并设置为双向,TState 设置为 TS_ENTER,将空的 _EntryList 队列设置为「逆序的双向链表」
  |   |   |   |   |   |   |-else // QMode == 0 or QMode == 2,// 将 _EntryList 队列设置为「已脱离的 _cxq 队列的链表」
  |   |   |   |   |   |   | // 执行到这里说明 _cxq 队列为空
  |   |   |   |   |   |   | // 若 QMode 等于 1,则 _EntryList 是「逆序的」「双向的」已脱离的 _cxq 队列的链表
  |   |   |   |   |   |   | // 若 QMode 等于 0 或 2,则 _EntryList 是「顺序」 「双向的」已脱离的 _cxq 队列的链表
  |   |   |   |   |   |   |-if (_succ != NULL) // 如果当前对象的 ObjectMonitor 的 _succ 后继者不为空,直接执行下一轮循环
  |   |   |   |   |   |   |   |-continue; // 直接继续下一轮循环
  |   |   |   |   |   |   |-w = _EntryList // w 指针指向 _EntryList 双向队列的头节点
  |   |   |   |   |   |   |-if (w != NULL)
  |   |   |   |   |   |   |   |-ExitEpilog (Self, w) // 执行 ExitEpilog 方法,设置当前 ObjectMonitor 对象的后继者 _succ 为 _EntryList 头节点的线程,并唤醒此节点线程 (Thread->_ParkEvent->unpark())
  |   |   |   |   |   |   |   |-return; // 直接退出

bytecodeInterpreter 方法 bytecodeInterpreter | #define ARRAY_STOREFROM64 | CASE(_monitorexit)

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp#L1923-L1953

CASE(_monitorexit): {
  oop lockee = STACK_OBJECT(-1); // 锁对象
  CHECK_NULL(lockee);
  BasicObjectLock* limit = istate->monitor_base();
  BasicObjectLock* most_recent = (BasicObjectLock*) istate->stack_base();
  while (most_recent != limit ) { // 从栈底遍历到栈顶
    // 找到 BasicObjectLock (即 LockRecord) 的 obj 等于锁对象
    if ((most_recent)->obj() == lockee) {
      // 获取锁
      BasicLock* lock = most_recent->lock();
      markOop header = lock->displaced_header();
      // 设置将 BasicObjectLock (即 LockRecord) 中的_obj设置为空
      // 如果是偏向锁,只需要释放 BasicObjectLock (即 LockRecord) 就行
      most_recent->set_obj(NULL);
      if (!lockee->mark()->has_bias_pattern()) { // 如果不是偏向锁,走轻量级或者重量级锁的释放流程
        bool call_vm = UseHeavyMonitors;
        // If it isn't recursive we either must swap old header or call the runtime
        if (header != NULL || call_vm) { // header 为空即代表轻量级锁重入,轻量级锁只需要处理第一次 Lock Record 
          if (call_vm || Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { // CAS 设置为原来 markword (即存放在 Lock Record 的 markword)
            // restore object for the slow case
            most_recent->set_obj(lockee);
            CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception);
          }
        }
      }
      UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); // 执行下一条命令
    }
    most_recent++;
  }
  CALL_VM(InterpreterRuntime::throw_illegal_monitor_state_exception(THREAD), handle_exception);
  ShouldNotReachHere();
}

InterpreterRuntime::monitorexit 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp#L645-L662

IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem))
#ifdef ASSERT
  thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
  Handle h_obj(thread, elem->obj());
  assert(Universe::heap()->is_in_reserved_or_null(h_obj()),
         "must be NULL or an object");
  if (elem == NULL || h_obj()->is_unlocked()) {
    THROW(vmSymbols::java_lang_IllegalMonitorStateException());
  }
  // 直接调用 slow_exit
  ObjectSynchronizer::slow_exit(h_obj(), elem->lock(), thread);
  // Free entry. This must be done here, since a pending exception might be installed on
  // exit. If it is not cleared, the exception handling code will try to unlock the monitor again.
  elem->set_obj(NULL);
#ifdef ASSERT
  thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
IRT_END

ObjectSynchronizer::slow_exit 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/synchronizer.cpp#L272-L274

void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
  fast_exit(object, lock, THREAD) ;
}

ObjectSynchronizer:: fast_exit 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/synchronizer.cpp#L186-L222

void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
  assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here");
  markOop dhw = lock->displaced_header();
  markOop mark ;
  // Lock Record 存放的 markword 为空,说明是重入的情况,这里面没有做实际的操作就返回了
  if (dhw == NULL) {
     mark = object->mark() ;
     assert (!mark->is_neutral(), "invariant") ;
     if (mark->has_locker() && mark != markOopDesc::INFLATING()) {
        assert(THREAD->is_lock_owned((address)mark->locker()), "invariant") ;
     }
     if (mark->has_monitor()) {
        ObjectMonitor * m = mark->monitor() ;
        assert(((oop)(m->object()))->mark() == mark, "invariant") ;
        assert(m->is_entered(THREAD), "invariant") ;
     }
     return ;
  }
  mark = object->mark() ;
  // 锁对象的 markword 等于 Lock Record 的地址,说明是「轻量级锁」,进行 CAS 设置
  if (mark == (markOop) lock) {
     assert (dhw->is_neutral(), "invariant") ;
     // 以「Lock Record 存放的原 markword」作为替换值,以「锁对象的 wordword」作为比较值,CAS 设置「锁对象的 markword 内存」值,成功直接返回
     if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) {
        TEVENT (fast_exit: release stacklock) ;
        return;
     }
  }
  // 走到这里说明符合任一条件,case1: 当前是「重量级锁」 case2: 是轻量级锁,但 CAS 失败 (即解锁时发生竞争)
  // 需要膨胀为重量级锁,膨胀完再调用 ObjectMonitor::exit 方法
  ObjectSynchronizer::inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD);
}

ObjectMonitor::exit 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L962-L1284

void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) {
   Thread * Self = THREAD ;
   // 如果 ObjectMonitor 对象的 _owner 不是当前线程
   if (THREAD != _owner) {
     // 判断 _owner 是否在当前线程栈中的 Lock Record 地址范围中
     // 在,说明是当前线程持有「轻量级锁」,但是有其他线程竞争,进行 inflate 和初始化 ObjectMonitor 对象,
     // 升级锁为「重量级锁」,并设置 _owner 是当前线程的 Lock Record (BasicObjectLock->_obj 是锁对象) 地址
     if (THREAD->is_lock_owned((address) _owner)) {
       assert (_recursions == 0, "invariant") ;
       _owner = THREAD ; // 修改 ObjectMonitor 对象的 _owner 为当前线程
       _recursions = 0 ; // 设置重入次数为 0
       OwnerIsThread = 1 ; // 设置 OwnerIsThread 为 1
     } else { // 如果 ObjectMonitor 对象的 _owner 不是当前线程,也不是在持有轻量级锁的线程的 Lock Record 地址范围内,说明发生异常,直接退出当前方法
       TEVENT (Exit - Throw IMSX) ;
       assert(false, "Non-balanced monitor enter/exit!");
       if (false) {
          THROW(vmSymbols::java_lang_IllegalMonitorStateException());
       }
       return;
     }
   }

   // 如果当前 ObjectMonitor 对象的 _recursions 重入次数不等于 0,说明发生重入且不是第一次执行,只需要递减重入次数,退出当前方法
   if (_recursions != 0) {
     _recursions--;        // this is simple recursive enter // 递减重入次数
     TEVENT (Inflated exit - recursive) ;
     return ;
   }

   //SyncFlags & 100,即如果 SyncFlags 第 3 位是 0,将 ObjectMonitor 的负责线程 _Responsible 设置为 NULL 
   if ((SyncFlags & 4) == 0) {
      _Responsible = NULL ;
   }

#if INCLUDE_JFR
   if (not_suspended && EventJavaMonitorEnter::is_enabled()) {
    _previous_owner_tid = JFR_THREAD_ID(Self);
   }
#endif

   for (;;) { // 无限循环
      assert (THREAD == _owner, "invariant") ;

      // Knob_ExitPolicy 默认为 0
      if (Knob_ExitPolicy == 0) {
         // 调用操作系统相关的 OrderAccess::release_store_ptr 将当前 ObjectMonitor 对象的 _owner 设置为 NULL,即释放「重量级锁锁」
         // 注意:此时如果有其他线程进入同步块则能获得「重量级锁」
         OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
         OrderAccess::storeload() ;                         // See if we need to wake a successor
         // 如果「等待队列 _EntryList」和「等待队列 _cxq」都是空队列,或者当前 ObjectMonitor 对象的 _succ 后继者已经被指定好,直接退出方法
         // 表明没有竞争者,或者已经指定好下一个竞争者
         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
            TEVENT (Inflated exit - simple egress) ;
            return ;
         }
         TEVENT (Inflated exit - complex egress) ;

         // CAS 操作尝试将当前 ObjectMonitor 对象的 _owner,由「NULL」设置为「当前线程」
         // 如果设置失败,说明「重量级锁」已被其他线程获取,当前线程不需要做唤醒其他线程工作,直接退出当前方法
         // 因为只有具备 _owner 才能继续操作 _EntryList 和 _cxq
         if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
            return ;
         }
         TEVENT (Exit - Reacquired) ;
      } else { // Knob_ExitPolicy != 0 的情况
         // 如果「等待队列 _EntryList」和「等待队列 _cxq」都是空队列,或者当前 ObjectMonitor 对象的 _succ 后继者已经被指定好,表明没有竞争者,或者已经指定好下一个竞争者
         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
            // 调用操作系统相关的 OrderAccess::release_store_ptr 将当前 ObjectMonitor 对象的 _owner 设置为 NULL,即释放「重量级锁锁」
            OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
            OrderAccess::storeload() ;
            // Ratify the previously observed values.
            // 如果“_cxq 为 NULL”或者“当前 ObjectMonitor 对象的 _succ 后继者已经被指定好”,直接退出方法
            if (_cxq == NULL || _succ != NULL) {
                TEVENT (Inflated exit - simple egress) ;
                return ;
            }

            // CAS 操作尝试将当前 ObjectMonitor 对象的 _owner,由「NULL」设置为「当前线程」
            // 如果设置失败,说明「重量级锁」已被其他线程获取,当前线程不需要做唤醒其他线程工作,直接退出当前方法
            // 因为只有具备 _owner 才能继续操作 _EntryList 和 _cxq
            if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
               TEVENT (Inflated exit - reacquired succeeded) ;
               return ;
            }
            TEVENT (Inflated exit - reacquired failed) ;
         } else {
            TEVENT (Inflated exit - complex egress) ;
         }
      }

      guarantee (_owner == THREAD, "invariant") ;

      ObjectWaiter * w = NULL ;
      // 根据 QMode 的不同会有不同的唤醒策略,Knob_QMode 默认是 0
      int QMode = Knob_QMode ;

      // QMode 为 2,表示优先处理 _cxq 队列头节点 (_cxq 等待队列中的 ObjectWaiter 节点的线程优先级更高)
      // 唤醒 _cxq 队列的头节点的线程,并直接退出当前方法
      if (QMode == 2 && _cxq != NULL) {
          // QMode == 2 : cxq has precedence over EntryList.
          // 取 _cxq 队列头节点 (快照,因为若有线程此时竞争重量级锁失败,将自己封装成 ObjectWaiter node 进行 CAS 设置 _cxq 队列头节点)
          w = _cxq ;
          assert (w != NULL, "invariant") ;
          assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
          // 执行 ExitEpilog 方法,设置当前 ObjectMonitor 对象的后继者 _succ 为 w 节点的线程,并唤醒 w 节点线程 (Thread->_ParkEvent->unpark())
          ExitEpilog (Self, w) ;
          return ; // 直接退出方法
      }

      // QMode 为 3,表示将 _cxq 的节点批量转移到 _EntryList 队列的「队尾」,w 指向原 _cxq 的队列头节点
      if (QMode == 3 && _cxq != NULL) {
          // 取 _cxq 队列头节点 (快照,因为若有线程此时竞争重量级锁失败,将自己封装成 ObjectWaiter node 进行 CAS 设置 _cxq 队列头节点)
          w = _cxq ;
          for (;;) { // 无限循环
             assert (w != NULL, "Invariant") ;
             // 以「w 快照头节点」作为比较值,以「NULL」作为替换值,CAS 尝试修改「_cxq 队列的头节点」,目的是将 _cxq 的头节点脱离,即把 _cxq 清空
             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
             if (u == w) break ; // 说明 w 此时就是 _cxq 队列头节点,退出循环
             // 执行到这里,说明 _cxq 队列头节点,已被修改,重新将 w 设置最新的头节点,继续下一轮循环
             w = u ;
          }
          assert (w != NULL              , "invariant") ;

          ObjectWaiter * q = NULL ;
          ObjectWaiter * p ;
          // 遍历已脱离的 _cxq 队列的链表,将每个节点修改为双向链表节点,且修改节点的 Tstate 为 TS_ENTER
          for (p = w ; p != NULL ; p = p->_next) {
              guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
              p->TState = ObjectWaiter::TS_ENTER ;
              p->_prev = q ;
              q = p ;
          }

          ObjectWaiter * Tail ;
          // 遍历 _EntryList 队列,直至找到双链表的尾节点,将 Tail 指针指向 _EntryList 队列的尾节点
          for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;
          // 如果尾节点为空说明,_EntryList 为空,直接将 _EntryList 设置为「已脱离的 _cxq 队列并被修改为双向节点且 TState 是 TS_ENTER 的链表」
          if (Tail == NULL) {
              _EntryList = w ;
          } else { // _EntryList 不为空,用尾插法连接「已脱离的 _cxq 队列并被修改为双向节点且 TState 是 TS_ENTER 的链表」
              Tail->_next = w ;
              w->_prev = Tail ;
          }
      }

      // QMode 为 4,表示将 _cxq 的节点批量转移到 _EntryList 队列的「队首」,w 指向原 _cxq 的队列头节点,同时也是新 _EntryList 队列头节点
      if (QMode == 4 && _cxq != NULL) {
          // 取 _cxq 队列头节点 (快照,因为若有线程此时竞争重量级锁失败,将自己封装成 ObjectWaiter node 进行 CAS 设置 _cxq 队列头节点)
          w = _cxq ;
          for (;;) { // 无限循环
             assert (w != NULL, "Invariant") ;
             // 以「w 快照头节点」作为比较值,以「NULL」作为替换值,CAS 尝试修改「_cxq 队列的头节点」,目的是将 _cxq 的头节点脱离,即把 _cxq 清空
             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
             if (u == w) break ; // 说明 w 此时就是 _cxq 队列头节点,退出循环
             // 执行到这里,说明 _cxq 队列头节点,已被修改,重新将 w 设置最新的头节点,继续下一轮循环
             w = u ;
          }
          assert (w != NULL              , "invariant") ;

          ObjectWaiter * q = NULL ;
          ObjectWaiter * p ;
          // 遍历已脱离的 _cxq 队列的链表,将每个节点修改为双向链表节点,且修改节点的 Tstate 为 TS_ENTER
          for (p = w ; p != NULL ; p = p->_next) {
              guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
              p->TState = ObjectWaiter::TS_ENTER ;
              p->_prev = q ;
              q = p ;
          }

          // _EntryList 不为空,将「已脱离的 _cxq 队列并被修改为双向节点且 TState 是 TS_ENTER 的链表」的尾节点连接「_EntryList 队列头节点」
          if (_EntryList != NULL) {
              q->_next = _EntryList ;
              _EntryList->_prev = q ;
          }
          // 修改 _EntryList 指向新的队列头节点
          _EntryList = w ;
      }

      // w 指针指向 _EntryList 队列的头节点
      w = _EntryList  ;
      // _EntryList 队列不为空,直接唤醒头节点的线程,并直接返回当前方法
      if (w != NULL) {
          assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
          // 执行 ExitEpilog 方法,设置当前 ObjectMonitor 对象的后继者 _succ 为 _EntryList 头节点的线程,并唤醒此节点线程 (Thread->_ParkEvent->unpark())
          ExitEpilog (Self, w) ;
          return ; // 直接返回当前方法
      }

      // 执行到这里说明 _EntryList 为空,将 w 指针指向 _cxq 队列的头节点 (快照)
      w = _cxq ;
      // _EntryList 和 _cxq 都为空,直接继续下一轮循环
      if (w == NULL) continue ;

      // 执行到这里说明 _EntryList 队列为空,但 _cxq 队列不为空,w 指针指向 _cxq 队列的头节点 (快照)
      for (;;) { // 无限循环
          assert (w != NULL, "Invariant") ;
          // 以「w 快照头节点」作为比较值,以「NULL」作为替换值,CAS 尝试修改「_cxq 队列的头节点」,目的是将 _cxq 的头节点脱离,即把 _cxq 清空
          ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
          if (u == w) break ; // 说明 w 此时就是 _cxq 队列头节点,退出循环
          // 执行到这里,说明 _cxq 队列头节点,已被修改,重新将 w 设置最新的头节点,继续下一轮循环
          w = u ;
      }
      TEVENT (Inflated exit - drain cxq into EntryList) ;

      assert (w != NULL              , "invariant") ;
      assert (_EntryList  == NULL    , "invariant") ;

      // 执行到这里说明 _EntryList 队列为空,但 _cxq 队列由不为空设置为空,w 指针指向「已脱离的 _cxq 队列的链表」的头节点
      // QMode 为 1,表示将「已脱离的 _cxq 队列的链表」,进行逆序,并设置为双向,TState 设置为 TS_ENTER,
      // 将空的 _EntryList 队列设置为「逆序的双向链表」
      if (QMode == 1) {
         // QMode == 1 : drain cxq to EntryList, reversing order
         // We also reverse the order of the list.
         ObjectWaiter * s = NULL ;
         ObjectWaiter * t = w ;
         ObjectWaiter * u = NULL ;
         while (t != NULL) {
             guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ;
             t->TState = ObjectWaiter::TS_ENTER ;
             u = t->_next ;
             t->_prev = u ;
             t->_next = s ;
             s = t;
             t = u ;
         }
         _EntryList  = s ;
         assert (s != NULL, "invariant") ;
      } else {
         // 执行到这里说明,QMode 是 0 (默认) 或 2,_EntryList 队列为空,但 _cxq 队列由不为空设置为空,w 指针指向「已脱离的 _cxq 队列的链表」的头节点
         // QMode == 0 or QMode == 2
         // 将 _EntryList 队列设置为「已脱离的 _cxq 队列的链表」
         _EntryList = w ;
         ObjectWaiter * q = NULL ;
         ObjectWaiter * p ;
         // 遍历已脱离的 _cxq 队列的链表,将每个节点修改为双向链表节点,且修改节点的 Tstate 为 TS_ENTER
         for (p = w ; p != NULL ; p = p->_next) {
             guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
             p->TState = ObjectWaiter::TS_ENTER ;
             p->_prev = q ;
             q = p ;
         }
      }

      // 此时,_cxq 队列为空
      // 若 QMode 等于 1,则 _EntryList 是「逆序的」「双向的」已脱离的 _cxq 队列的链表
      // 若 QMode 等于 0 或 2,则 _EntryList 是「顺序」 「双向的」已脱离的 _cxq 队列的链表

      // 如果当前对象的 ObjectMonitor 的 _succ 后继者不为空,直接执行下一轮循环
      if (_succ != NULL) continue;

      // w 指针指向 _EntryList 双向队列的头节点
      w = _EntryList  ;
      if (w != NULL) {
          guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
          // 执行 ExitEpilog 方法,设置当前 ObjectMonitor 对象的后继者 _succ 为 _EntryList 头节点的线程,并唤醒此节点线程 (Thread->_ParkEvent->unpark())
          ExitEpilog (Self, w) ;
          // 直接退出当前方法
          return ;
      }
   }
}

ObjectMonitor::ExitEpilog 方法

源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/objectMonitor.cpp#L1333-L1365

void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {
   assert (_owner == Self, "invariant") ;

   // Exit protocol:
   // 1. ST _succ = wakee
   // 2. membar #loadstore|#storestore;
   // 2. ST _owner = NULL
   // 3. unpark(wakee)

   // 将当前 ObjectMonitor 对象的 _succ 设置为 Wakee (需要被唤醒线程的 ObjectWaiter 节点 Wakee) 的线程
   _succ = Knob_SuccEnabled ? Wakee->_thread : NULL ; // Knob_SuccEnabled 默认是 1 (0 限制无效唤醒)
   // 取出 Wakee 线程的 Thread->_ParkEvent
   ParkEvent * Trigger = Wakee->_event ;

   // 一旦设置了当前 ObjectMonitor 对象的 _owner 为 NULL,即释放了重量锁,
   // 就无法保证安全解除对 Wakee 的引用,因为获取到重量级锁的线程会将 Wakee 节点从 _cxq 或者 _EntryList 移除
   // 为了安全解除对 Wakee 的引用,设置 Wakee 引用为 NULL
   Wakee  = NULL ;

   // 调用操作系统相关的 OrderAccess::release_store_ptr 将当前 ObjectMonitor 对象的 _owner 设置为 NULL,即释放「重量级锁锁」
   OrderAccess::release_store_ptr (&_owner, NULL) ;
   // 内存屏障 storeload ,确保 store 操作 (写操作,将 _owner 设置为 NULL) 在 load 操作 (读操作, ) 之前
   // 让编译器和 CPU 不要进行指令重排序
   // 和保证 CPU 的缓存强一致性 (将 CPU 写操作前将 store buffer 的数据都刷到 Cache 中,读操作前将 invaild queue 数据都作用到 Cache 让其缓存失效)
   OrderAccess::fence() ;                               // ST _owner vs LD in unpark()

   if (SafepointSynchronize::do_call_back()) {
      TEVENT (unpark before SAFEPOINT) ;
   }

   DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
   // 唤醒 Wakee 的线程,调用 Thread->_ParkEvent->unpark() 方法
   Trigger->unpark() ;

   // Maintain stats and report events to JVMTI
   if (ObjectMonitor::_sync_Parks != NULL) {
      ObjectMonitor::_sync_Parks->inc() ;
   }
}