Hotspot 重量級鎖ObjectMonitor(二) 源碼解析

   目錄

1、AddWaiter / DequeueWaiter /DequeueSpecificWaiter

2、wait

3、notify

4、notifyAll

5、exit

6、try_enter / complete_exit

7、總結


本篇博客繼續上一篇《Hotspot 重量級鎖ObjectMonitor(一) 源碼解析》將ObjectMonitor的其他關鍵方法的實現。

1、AddWaiter / DequeueWaiter /DequeueSpecificWaiter

      AddWaiter方法用於將目標ObjectWaiter加入到雙向循環鏈表中,DequeueWaiter用於移除鏈表頭_WaitSet對應的節點,該節點是最早加入到鏈表的,即按照加入鏈表的先後順序依次從鏈表中移除,DequeueSpecificWaiter用於移除指定節點,不一定是_WaitSet對應的節點。其實現如下:

inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
  assert(node != NULL, "should not dequeue NULL node");
  assert(node->_prev == NULL, "node already in list");
  assert(node->_next == NULL, "node already in list");
  //將目標節點放入一個雙向的循環鏈表中
  if (_WaitSet == NULL) {
    //如果_WaitSet還是空的,當前節點就是第一個
    _WaitSet = node;
    node->_prev = node;
    node->_next = node;
  } else {
    //如果_WaitSet不是空的,將其插入到head的prev節點上
    ObjectWaiter* head = _WaitSet ;
    ObjectWaiter* tail = head->_prev;
    assert(tail->_next == head, "invariant check");
    //注意tail在初始狀態下就是head,所以插入第二個節點時修改next屬性,實際是修改head的next屬性
    tail->_next = node;
    head->_prev = node;
    node->_next = head;
    node->_prev = tail;
  }
}

inline ObjectWaiter* ObjectMonitor::DequeueWaiter() {
  // dequeue the very first waiter
  ObjectWaiter* waiter = _WaitSet;
  if (waiter) {
    //如果_WaitSet爲不空
    DequeueSpecificWaiter(waiter);
  }
  return waiter;
}

inline void ObjectMonitor::DequeueSpecificWaiter(ObjectWaiter* node) {
  assert(node != NULL, "should not dequeue NULL node");
  assert(node->_prev != NULL, "node already removed from list");
  assert(node->_next != NULL, "node already removed from list");
  //從_WaitSet中取出一個ObjectWaiter,實際就是取出_WaitSet對應的head節點,該
  //節點是最早加入到鏈表中的
  ObjectWaiter* next = node->_next;
  if (next == node) {
    //_WaitSet只有一個節點
    assert(node->_prev == node, "invariant check");
    _WaitSet = NULL;
  } else {
    //將node從鏈表中移除
    ObjectWaiter* prev = node->_prev;
    assert(prev->_next == node, "invariant check");
    assert(next->_prev == node, "invariant check");
    next->_prev = prev;
    prev->_next = next;
    if (_WaitSet == node) {
      //如果移除的就是_WaitSet,將next置爲_WaitSet
      _WaitSet = next;
    }
  }
  //相關屬性置爲null
  node->_next = NULL;
  node->_prev = NULL;
}

 上述邏輯可以結合以下用例來理解,如下:

//依次添加node,node2,node3,node4,node5 5個節點時各節點的引用關係
prev        next
----------------  
node  node  node
=================
node2 node  node2
node  node2 node
=================
node  node2 node3
node3 node  node2
node2 node3 node
=================
node2 node3 node4
node4 node  node2
node3 node4  node 
node  node2 node3 //node2節點的引用關係不變
=================
node3 node4 node5
node5 node  node2
node4 node5 node
node  node2 node3 //node2和node3節點的引用關係不變
node2 node3 node4

刪除node節點後node2作爲_WaitSet
================
node4 node5 node2
node5 node2 node3
node  node2 node3 //node2和node3節點的引用關係不變
node2 node3 node4

2、wait

     wait方法是Object的wait方法的底層實現,該方法會創建一個ObjectWaiter並加入到鏈表中,然後釋放佔有的鎖,讓當前線程休眠,噹噹前線程因爲等待超時,被中斷或者被其他線程喚醒時就再次搶佔鎖,搶佔邏輯就是之前的enter方法,搶佔成功後wait方法退出。

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
   //獲取當前線程
   Thread * const Self = THREAD ;
   assert(Self->is_Java_thread(), "Must be Java thread!");
   JavaThread *jt = (JavaThread *)THREAD;
   
   //初始化配置,如果已經初始化則返回
   DeferredInitialize () ;

   //檢查當前線程是否獲取了鎖,如果沒有則拋出異常
   CHECK_OWNER();

   EventJavaMonitorWait event;

   //如果線程被中斷了且不是因爲未處理異常導致的
   if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
     //發佈JVMTI事件
     if (JvmtiExport::should_post_monitor_waited()) {
        JvmtiExport::post_monitor_waited(jt, this, false);
     }
     if (event.should_commit()) {
       post_monitor_wait_event(&event, 0, millis, false);
     }
     TEVENT (Wait - Throw IEX) ;
     //拋出異常
     THROW(vmSymbols::java_lang_InterruptedException());
     return ;
   }

   TEVENT (Wait) ;

   assert (Self->_Stalled == 0, "invariant") ;
   //設置屬性,記錄當前線程等待的ObjectMonitor
   Self->_Stalled = intptr_t(this) ;
   jt->set_current_waiting_monitor(this);

   //創建ObjectWaiter,將其狀態置爲TS_WAIT
   ObjectWaiter node(Self);
   node.TState = ObjectWaiter::TS_WAIT ;
   Self->_ParkEvent->reset() ;
   OrderAccess::fence();          // ST into Event; membar ; LD interrupted-flag

   //獲取操作ObjectWaiter鏈表的鎖_WaitSetLock
   Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;
   //將當前節點插入到ObjectWaiter鏈表中
   AddWaiter (&node) ;
   //釋放鎖
   Thread::SpinRelease (&_WaitSetLock) ;
   
   //SyncFlags默認爲0
   if ((SyncFlags & 4) == 0) {
      _Responsible = NULL ;
   }
   intptr_t save = _recursions; // record the old recursion count
   //等待的線程數加1
   _waiters++;                  // increment the number of waiters
   _recursions = 0;             // set the recursion level to be 1
   //釋放該鎖
   exit (true, Self) ;                    // exit the monitor
   guarantee (_owner != Self, "invariant") ;

   // TODO-FIXME: change the following logic to a loop of the form
   //   while (!timeout && !interrupted && _notified == 0) park()
   int ret = OS_OK ;
   int WasNotified = 0 ;
   { // State transition wrappers
     OSThread* osthread = Self->osthread();
     //修改線程狀態爲OBJECT_WAIT
     OSThreadWaitState osts(osthread, true);
     {
       //修改線程狀態從_thread_in_vm到_thread_blocked
       ThreadBlockInVM tbivm(jt);
       // Thread is in thread_blocked state and oop access is unsafe.
       jt->set_suspend_equivalent();

       if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
           // Intentionally empty
       } else
       if (node._notified == 0) { //_notified爲0表示沒有其他線程喚醒
         //將當前線程park,讓其處於休眠狀態
         if (millis <= 0) {
            Self->_ParkEvent->park () ;
         } else {
            ret = Self->_ParkEvent->park (millis) ;
         }
       }

       //當前線程從park狀態被喚醒了
       //ExitSuspendEquivalent默認返回false
       if (ExitSuspendEquivalent (jt)) {
          // TODO-FIXME: add -- if succ == Self then succ = null.
          jt->java_suspend_self();
       }

     } //退出代碼塊時會切換線程狀態 _thread_blocked -> _thread_in_vm
     
     //如果是線程被中斷或者等待超時則狀態是TS_WAIT,如果是被nofity喚醒的則應該是TS_RUN 
     if (node.TState == ObjectWaiter::TS_WAIT) {
         //獲取鎖
         Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
         if (node.TState == ObjectWaiter::TS_WAIT) {
            //如果是TS_WAIT,則將其從鏈表中移除
            DequeueSpecificWaiter (&node) ;       // unlink from WaitSet
            assert(node._notified == 0, "invariant");
            //將狀態置爲TS_RUN
            node.TState = ObjectWaiter::TS_RUN ;
         }
         //釋放鎖
         Thread::SpinRelease (&_WaitSetLock) ;
     }

     guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ;
     //讓修改立即生效
     OrderAccess::loadload() ;
     if (_succ == Self) _succ = NULL ;
     WasNotified = node._notified ;

     // post monitor waited event. Note that this is past-tense, we are done waiting.
     if (JvmtiExport::should_post_monitor_waited()) {
       JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);

       if (node._notified != 0 && _succ == Self) {
         node._event->unpark();
       }
     }

     if (event.should_commit()) {
       post_monitor_wait_event(&event, node._notifier_tid, millis, ret == OS_TIMEOUT);
     }

     OrderAccess::fence() ;

     assert (Self->_Stalled != 0, "invariant") ;
     Self->_Stalled = 0 ;

     assert (_owner != Self, "invariant") ;
     ObjectWaiter::TStates v = node.TState ;
     if (v == ObjectWaiter::TS_RUN) {
        //重新獲取該鎖
         enter (Self) ;
     } else {
         //該ObjectWaiter已經被喚醒了,但是等待獲取鎖的時候線程被中斷了
         guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
         ReenterI (Self, &node) ;
         node.wait_reenter_end(this);
     }

     guarantee (node.TState == ObjectWaiter::TS_RUN, "invariant") ;
     assert    (_owner == Self, "invariant") ;
     assert    (_succ != Self , "invariant") ;
   } // OSThreadWaitState()

   jt->set_current_waiting_monitor(NULL);

   guarantee (_recursions == 0, "invariant") ;
   _recursions = save;     // restore the old recursion count
   _waiters--;             // decrement the number of waiters

   // Verify a few postconditions
   assert (_owner == Self       , "invariant") ;
   assert (_succ  != Self       , "invariant") ;
   assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;

   if (SyncFlags & 32) {
      OrderAccess::fence() ;
   }

   //如果不是因爲notify被喚醒
   if (!WasNotified) {
     // 可能因爲等待超時或者Thread.interrupt()被喚醒
     if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
       TEVENT (Wait - throw IEX from epilog) ;
      //如果線程中斷則拋出異常
       THROW(vmSymbols::java_lang_InterruptedException());
     }
   }
}

#define CHECK_OWNER()                                                             \
  do {                                                                            \
    if (THREAD != _owner) {                                                       \
      //如果owner屬性不是當前線程
      if (THREAD->is_lock_owned((address) _owner)) {                              \
        //如果owner屬性位於當前線程棧幀中,說明該鎖是由輕量級鎖膨脹來的
        //修改owner屬性爲當前線程
        _owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \
        _recursions = 0;                                                          \
        OwnerIsThread = 1 ;                                                       \
      } else {                                                                    \
        //當前線程沒有獲取鎖,則拋出異常
        TEVENT (Throw IMSX) ;                                                     \
        THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \
      }                                                                           \
    }                                                                             \
  } while (false)

bool Thread::is_interrupted(Thread* thread, bool clear_interrupted) {
  trace("is_interrupted", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  // 判斷其是否被中斷,如果是且clear_interrupted爲true,則將其中斷標識清除掉
  return os::is_interrupted(thread, clear_interrupted);
}

bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
    "possibility of dangling Thread pointer");
    //獲取關聯的原生線程
  OSThread* osthread = thread->osthread();
  //獲取其是否被中斷
  bool interrupted = osthread->interrupted();
  if (interrupted && clear_interrupted) {
     //清除被中斷標識
    osthread->set_interrupted(false);
  }

  return interrupted;
}

//ReenterI和EnterI的邏輯基本相同,用於獲取對象鎖
void ATTR ObjectMonitor::ReenterI (Thread * Self, ObjectWaiter * SelfNode) {
    assert (Self != NULL                , "invariant") ;
    assert (SelfNode != NULL            , "invariant") ;
    assert (SelfNode->_thread == Self   , "invariant") ;
    assert (_waiters > 0                , "invariant") ;
    //校驗目標對象的對象頭就是當前ObjectMonitor的指針
    assert (((oop)(object()))->mark() == markOopDesc::encode(this) , "invariant") ;
    assert (((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
    JavaThread * jt = (JavaThread *) Self ;

    int nWakeups = 0 ;
    for (;;) {
        ObjectWaiter::TStates v = SelfNode->TState ;
        //校驗狀態
        guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
        assert    (_owner != Self, "invariant") ;
        
        //嘗試獲取鎖
        if (TryLock (Self) > 0) break ;
        //嘗試自旋獲取鎖
        if (TrySpin (Self) > 0) break ;

        TEVENT (Wait Reentry - parking) ;

        {   
           //修改線程狀態
           OSThreadContendState osts(Self->osthread());
           ThreadBlockInVM tbivm(jt);

           jt->set_suspend_equivalent();
           //SyncFlags默認是0
           if (SyncFlags & 1) {
              Self->_ParkEvent->park ((jlong)1000) ;
           } else {
              Self->_ParkEvent->park () ;
           }

           // were we externally suspended while we were waiting?
           for (;;) {
              //ExitSuspendEquivalent默認返回false
              if (!ExitSuspendEquivalent (jt)) break ;
              if (_succ == Self) { _succ = NULL; OrderAccess::fence(); }
              jt->java_suspend_self();
              jt->set_suspend_equivalent();
           }
        }

        //嘗試獲取鎖
        if (TryLock(Self) > 0) break ;

        TEVENT (Wait Reentry - futile wakeup) ;
        ++ nWakeups ;

        // Assuming this is not a spurious wakeup we'll normally
        // find that _succ == Self.
        if (_succ == Self) _succ = NULL ;

        // Invariant: after clearing _succ a contending thread
        // *must* retry  _owner before parking.
        OrderAccess::fence() ;

        if (ObjectMonitor::_sync_FutileWakeups != NULL) {
          ObjectMonitor::_sync_FutileWakeups->inc() ;
        }
    }//for循環結束

    //for循環結束,已經獲取了鎖
    assert (_owner == Self, "invariant") ;
    assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
    //從鏈表中移除
    UnlinkAfterAcquire (Self, SelfNode) ;
    if (_succ == Self) _succ = NULL ;
    assert (_succ != Self, "invariant") ;
    //修改狀態爲TS_RUN
    SelfNode->TState = ObjectWaiter::TS_RUN ;
    OrderAccess::fence() ;      // see comments at the end of EnterI()
}

3、notify

     notify方法時Object的notify方法的底層實現,用於“喚醒”WaitSet鏈表頭對應的線程,即最早加入到該鏈表的等待線程,注意在默認配置下(默認的處理策略是2,不同策略的處理邏輯不同),並不會直接unpark該線程,而是將其加入到cxq鏈表的前面,相當於調用了一次EnterI方法。加入到cxq鏈表後,當關聯的鎖被釋放了就會unpark該線程,注意只是喚醒,然後該線程調用enter方法搶佔鎖,因此此時可能有其他線程在同時調用enter方法搶佔鎖。

void ObjectMonitor::notify(TRAPS) {
  //檢查當前線程是否佔用該鎖,如果沒有拋出異常
  CHECK_OWNER();
  if (_WaitSet == NULL) {
     //如果沒有等待的線程則退出
     TEVENT (Empty-Notify) ;
     return ;
  }
  
  //Knob_MoveNotifyee屬性默認是2
  int Policy = Knob_MoveNotifyee ;
  
  //獲取鎖
  Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ;
  //將鏈表頭元素移除並返回
  ObjectWaiter * iterator = DequeueWaiter() ;
  if (iterator != NULL) {
     TEVENT (Notify1 - Transfer) ;
     guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
     guarantee (iterator->_notified == 0, "invariant") ;
     if (Policy != 4) {
        //將狀態置爲TS_ENTER
        iterator->TState = ObjectWaiter::TS_ENTER ;
     }
     //_notified置爲1表示該ObjectWaiter被喚醒了
     iterator->_notified = 1 ;
     Thread * Self = THREAD;
     //記錄當前線程ID
     iterator->_notifier_tid = Self->osthread()->thread_id();

     ObjectWaiter * List = _EntryList ;
     if (List != NULL) {
        assert (List->_prev == NULL, "invariant") ;
        assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
        assert (List != iterator, "invariant") ;
     }
     
     //根據不同的策略執行不同的處理
     if (Policy == 0) {       //將iterator插入到_EntryList頭元素的前面
         if (List == NULL) {
             iterator->_next = iterator->_prev = NULL ;
             _EntryList = iterator ;
         } else {
             List->_prev = iterator ;
             iterator->_next = List ;
             iterator->_prev = NULL ;
             _EntryList = iterator ;
        }
     } else
     if (Policy == 1) {      //將iterator插入到_EntryList鏈表的末尾
         if (List == NULL) {
             iterator->_next = iterator->_prev = NULL ;
             _EntryList = iterator ;
         } else {
            ObjectWaiter * Tail ;
            //不斷遍歷找到鏈表最後一個元素
            for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
            assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
            Tail->_next = iterator ;
            iterator->_prev = Tail ;
            iterator->_next = NULL ;
        }
     } else
     if (Policy == 2) {      //將iterator插入到_cxq頭元素的前面
         // prepend to cxq
         if (List == NULL) {
             iterator->_next = iterator->_prev = NULL ;
             _EntryList = iterator ;
         } else {
            iterator->TState = ObjectWaiter::TS_CXQ ;
            for (;;) {
                ObjectWaiter * Front = _cxq ;
                iterator->_next = Front ;
                if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
                    break ;
                }
            }
         }
     } else
     if (Policy == 3) {      //將iterator插入到_cxq鏈表末尾的後面
        iterator->TState = ObjectWaiter::TS_CXQ ;
        for (;;) {
            ObjectWaiter * Tail ;
            Tail = _cxq ;
            if (Tail == NULL) {
                iterator->_next = NULL ;
                if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
                   break ;
                }
            } else {
                //往後遍歷找到最後一個元素
                while (Tail->_next != NULL) Tail = Tail->_next ;
                Tail->_next = iterator ;
                iterator->_prev = Tail ;
                iterator->_next = NULL ;
                break ;
            }
        }
     } else {
        //將等待的線程直接unpark喚醒
        ParkEvent * ev = iterator->_event ;
        iterator->TState = ObjectWaiter::TS_RUN ;
        OrderAccess::fence() ;
        ev->unpark() ;
     }

     if (Policy < 4) {
       //修改線程狀態,記錄鎖競爭開始
       iterator->wait_reenter_begin(this);
     }
  } //if結束
  
  //釋放鎖
  Thread::SpinRelease (&_WaitSetLock) ;

  if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) {
     //增加計數
     ObjectMonitor::_sync_Notifications->inc() ;
  }
}

4、notifyAll

      notifyAll方法就是Object的notifyAll方法的底層實現,對單個ObjectWaiter其處理邏輯跟notify是一致的,相比notify的實現就是增加了一個for循環,會不斷的從_WaitSet鏈表中移除頭元素,然後執行notify的處理邏輯,直到_WaitSet鏈表爲空退出循環。

void ObjectMonitor::notifyAll(TRAPS) {
  //檢查當前線程是否佔用該鎖,如果沒有拋出異常
  CHECK_OWNER();
  ObjectWaiter* iterator;
  if (_WaitSet == NULL) {
      //如果沒有等待的線程則退出
      TEVENT (Empty-NotifyAll) ;
      return ;
  }
  
  //Knob_MoveNotifyee屬性默認是2
  int Policy = Knob_MoveNotifyee ;
  int Tally = 0 ;
  //獲取鎖
  Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notifyall") ;
  
  //if變成for循環
  for (;;) {
     //獲取頭部元素,頭部節點爲最早加入到鏈表中的節點
     iterator = DequeueWaiter () ;
     //如果爲空則終止循環
     if (iterator == NULL) break ;
     TEVENT (NotifyAll - Transfer1) ;
    //增加計數
     ++Tally ;

     guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
     guarantee (iterator->_notified == 0, "invariant") ;
    //_notified置爲1表示該ObjectWaiter被喚醒了
     iterator->_notified = 1 ;
     Thread * Self = THREAD;
      //記錄當前線程ID
     iterator->_notifier_tid = Self->osthread()->thread_id();
     if (Policy != 4) {
        //將狀態置爲TS_ENTER
        iterator->TState = ObjectWaiter::TS_ENTER ;
     }

     //根據不同的策略執行不同的處理
     ObjectWaiter * List = _EntryList ;
     if (List != NULL) {
        assert (List->_prev == NULL, "invariant") ;
        assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
        assert (List != iterator, "invariant") ;
     }

     if (Policy == 0) {      //將iterator插入到_EntryList頭元素的前面
         if (List == NULL) {
             iterator->_next = iterator->_prev = NULL ;
             _EntryList = iterator ;
         } else {
             List->_prev = iterator ;
             iterator->_next = List ;
             iterator->_prev = NULL ;
             _EntryList = iterator ;
        }
     } else
     if (Policy == 1) {      //將iterator插入到_EntryList鏈表的末尾
         if (List == NULL) {
             iterator->_next = iterator->_prev = NULL ;
             _EntryList = iterator ;
         } else {
            ObjectWaiter * Tail ;
            for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
            assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
            Tail->_next = iterator ;
            iterator->_prev = Tail ;
            iterator->_next = NULL ;
        }
     } else
     if (Policy == 2) {     //將iterator插入到_cxq頭元素的前面
         // prepend to cxq
         iterator->TState = ObjectWaiter::TS_CXQ ;
         for (;;) {
             ObjectWaiter * Front = _cxq ;
             iterator->_next = Front ;
             if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
                 break ;
             }
         }
     } else
     if (Policy == 3) {      //將iterator插入到_cxq鏈表末尾的後面
        iterator->TState = ObjectWaiter::TS_CXQ ;
        for (;;) {
            ObjectWaiter * Tail ;
            Tail = _cxq ;
            if (Tail == NULL) {
                iterator->_next = NULL ;
                if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
                   break ;
                }
            } else {
                while (Tail->_next != NULL) Tail = Tail->_next ;
                Tail->_next = iterator ;
                iterator->_prev = Tail ;
                iterator->_next = NULL ;
                break ;
            }
        }
     } else {
        //將等待的線程直接unpark喚醒
        ParkEvent * ev = iterator->_event ;
        iterator->TState = ObjectWaiter::TS_RUN ;
        OrderAccess::fence() ;
        ev->unpark() ;
     }

     if (Policy < 4) {
     //修改線程狀態,記錄鎖競爭開始
       iterator->wait_reenter_begin(this);
     }
  }//for循環結束
  
  //釋放鎖
  Thread::SpinRelease (&_WaitSetLock) ;

  if (Tally != 0 && ObjectMonitor::_sync_Notifications != NULL) {
     //增加計數
     ObjectMonitor::_sync_Notifications->inc(Tally) ;
  }
}

5、exit

     exit用於釋放鎖,即將owner屬性置爲NULL,默認配置下會通過unpark喚醒_EntryList鏈表頭部節點對應的等待線程,如果EntryList鏈表爲空,則將cxq鏈表中的元素加入到EntryList鏈表中且順序保持不變,即優先喚醒最近等待的線程。注意exit方法並不會因爲安全點同步而阻塞,exit方法退出後繼續執行,無論解釋執行或者編譯執行則會都被阻塞;exit方式釋放鎖後,被喚醒的線程佔用了該鎖,在enter方法獲取鎖準備切換線程狀態時會被阻塞。

//第一個參數not_suspended用於debug的,可以忽略
void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) {
   Thread * Self = THREAD ;
   if (THREAD != _owner) {
     if (THREAD->is_lock_owned((address) _owner)) {
       //如果owner位於當前線程調用棧幀,說明該鎖是輕量級鎖膨脹來的
       assert (_recursions == 0, "invariant") ;
       //修改owner屬性
       _owner = THREAD ;
       _recursions = 0 ;
       OwnerIsThread = 1 ;
     } else {
       //其他線程佔用該鎖,直接返回
       TEVENT (Exit - Throw IMSX) ;
       assert(false, "Non-balanced monitor enter/exit!");
       if (false) {
          THROW(vmSymbols::java_lang_IllegalMonitorStateException());
       }
       return;
     }
   }

   if (_recursions != 0) {
     //不等於0說明是嵌套加鎖,將_recursions減1即可返回
     _recursions--;        // this is simple recursive enter
     TEVENT (Inflated exit - recursive) ;
     return ;
   }

   // SyncFlags默認值是0
   if ((SyncFlags & 4) == 0) {
      _Responsible = NULL ;
   }

   for (;;) {
      assert (THREAD == _owner, "invariant") ;
      
      //Knob_ExitPolicy默認值是0
      if (Knob_ExitPolicy == 0) {
         //將_owner屬性置爲NULL,釋放鎖,如果某個線程正在自旋搶佔該鎖,則會搶佔成功
         //即這種策略會優先保證通過自旋搶佔鎖的線程獲取鎖,而其他處於等待隊列中的線程則靠後
         OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
         //讓修改立即生效
         OrderAccess::storeload() ;                         // See if we need to wake a successor
         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
            //如果_EntryList或者cxq鏈表都是空的,則直接返回
            TEVENT (Inflated exit - simple egress) ;
            return ;
         }
         TEVENT (Inflated exit - complex egress) ;

         //如果_EntryList或者cxq鏈表不是空的,則原子的設置owner屬性爲當前線程,嘗試搶佔鎖
         if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
            //搶佔失敗則返回,等佔用該鎖的線程釋放後再處理鏈表中的等待線程
            return ;
         }
         TEVENT (Exit - Reacquired) ;
      } else {
         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
            OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
            OrderAccess::storeload() ;
            // Ratify the previously observed values.
            if (_cxq == NULL || _succ != NULL) {
                TEVENT (Inflated exit - simple egress) ;
                return ;
            }
            //有可能cxq插入了一個新節點,導致上面的if不成立,需要重新獲取鎖
            if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
               TEVENT (Inflated exit - reacquired succeeded) ;
               return ;
            }
            TEVENT (Inflated exit - reacquired failed) ;
         } else {
            //如果_EntryList或者cxq鏈表不是空的則不釋放鎖,避免二次搶佔鎖,即優先處理等待隊列中的線程
            TEVENT (Inflated exit - complex egress) ;
         }
      }

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

      ObjectWaiter * w = NULL ;
      //Knob_QMode的默認值是0
      int QMode = Knob_QMode ;

      if (QMode == 2 && _cxq != NULL) {
          w = _cxq ;
          assert (w != NULL, "invariant") ;
          assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
          //通過unpark喚醒cxq對應的線程,喚醒後會將cxq從鏈表中移除
          ExitEpilog (Self, w) ;
          return ;
      }

      if (QMode == 3 && _cxq != NULL) {
          //將cxq鏈表中的元素插入到_EntryList鏈表的末尾
          w = _cxq ;
          for (;;) {
             assert (w != NULL, "Invariant") ;
             //將_cxq原子的置爲NULL,如果失敗則更新w,重新嘗試直到成功爲止
             //置爲NULL後,如果有新的節點插入進來就形成了一個新的cxq鏈表
             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
             if (u == w) break ;
             w = u ;
          }
          assert (w != NULL              , "invariant") ;

          ObjectWaiter * q = NULL ;
          ObjectWaiter * p ;
          //遍歷cxq中的所有節點,將其置爲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找到末尾元素,將w插入到後面
          for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;
          if (Tail == NULL) {
              _EntryList = w ;
          } else {
              Tail->_next = w ;
              w->_prev = Tail ;
          }
      }

      if (QMode == 4 && _cxq != NULL) {
          //將cxq鏈表中的元素插入到_EntryList鏈表的頭部
          w = _cxq ;
          for (;;) {
             assert (w != NULL, "Invariant") ;
             //將_cxq原子的置爲NULL,如果失敗則更新w,重新嘗試直到成功爲止
             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
             if (u == w) break ;
             w = u ;
          }
          assert (w != NULL              , "invariant") ;

          ObjectWaiter * q = NULL ;
          ObjectWaiter * p ;
          //遍歷cxq中的所有節點,將其置爲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的頭部
          if (_EntryList != NULL) {
              q->_next = _EntryList ;
              _EntryList->_prev = q ;
          }
          _EntryList = w ;

      }

      w = _EntryList  ;
      if (w != NULL) {
          //通過unpark喚醒w對應的線程,喚醒後會該線程會負責將w從EntryList鏈表中移除
          assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
          ExitEpilog (Self, w) ;
          return ;
      }

      //如果_EntryList爲空
      w = _cxq ;
      if (w == NULL) continue ;//如果cxq爲空則重新循環,不會進入此分支

      //cxq不爲NULL
      for (;;) {
          assert (w != NULL, "Invariant") ;
          //將cxq原子的修改爲NULL
          ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
          if (u == w) break ;
          w = u ;
      }
      TEVENT (Inflated exit - drain cxq into EntryList) ;

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

      if (QMode == 1) {
         //遍歷cxq中的元素將其加入到_EntryList中,注意順序跟cxq中是返的
         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 or QMode == 2
         //遍歷cxq中的元素將其加入到_EntryList中,注意此時cxq鏈表的頭元素被賦值給EntryList
         _EntryList = w ;
         ObjectWaiter * q = NULL ;
         ObjectWaiter * p ;
         //cxq中的元素是通過next屬性串聯起來的,prev屬性沒有,此處遍歷加上prev屬性
         //當EntryList頭元素被移除了是取next屬性作爲EntryList
         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 ;
         }
      }

      if (_succ != NULL) continue;

      w = _EntryList  ;
      if (w != NULL) {
          guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
          //喚醒w對應的線程
          ExitEpilog (Self, w) ;
          return ;
      }
   }
}

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

   //Knob_SuccEnabled默認是1,succ表示很有可能佔用該鎖的線程
   _succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;
   ParkEvent * Trigger = Wakee->_event ;

   Wakee  = NULL ;

   //將owner屬性置爲NULL
   OrderAccess::release_store_ptr (&_owner, NULL) ;
   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);
   //喚醒目標線程
   Trigger->unpark() ;

   if (ObjectMonitor::_sync_Parks != NULL) {
      //增加計數
      ObjectMonitor::_sync_Parks->inc() ;
   }
}

6、try_enter / complete_exit

      try_enter用於實現Unsafe類的tryMonitorEnter方法,會嘗試獲取鎖,如果獲取失敗則直接返回false;complete_exit用於釋放目標鎖,在嵌套加鎖的情形下只需要調用complete_exit一次即可,如果是exit則需要調用多次。

bool ObjectMonitor::try_enter(Thread* THREAD) {
  if (THREAD != _owner) {
    if (THREAD->is_lock_owned ((address)_owner)) {
       //如果該線程已經佔有了該鎖,該鎖由輕量級鎖膨脹而來
       assert(_recursions == 0, "internal state error");
       //修改owner等屬性
       _owner = THREAD ;
       _recursions = 1 ;
       OwnerIsThread = 1 ;
       return true;
    }
    if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
       //原子的設置owner屬性,修改失敗
      return false;
    }
    //修改成功
    return true;
  } else {
    //當前線程已經佔有該鎖,將記錄嵌套加鎖的計數器加1
    _recursions++;
    return true;
  }
}

intptr_t ObjectMonitor::complete_exit(TRAPS) {
   Thread * const Self = THREAD;
   assert(Self->is_Java_thread(), "Must be Java thread!");
   JavaThread *jt = (JavaThread *)THREAD;

   DeferredInitialize();

   if (THREAD != _owner) {
    if (THREAD->is_lock_owned ((address)_owner)) {
       //如果是輕量級鎖膨脹來的
       assert(_recursions == 0, "internal state error");
       _owner = THREAD ;   /* Convert from basiclock addr to Thread addr */
       _recursions = 0 ;
       OwnerIsThread = 1 ;
    }
   }

   guarantee(Self == _owner, "complete_exit not owner");
   intptr_t save = _recursions; // record the old recursion count
   //_recursions置爲0,即嵌套加鎖的情形下不需要多次調用exit了
   _recursions = 0;        // set the recursion level to be 0
   //釋放該鎖
   exit (true, Self) ;           // exit the monitor
   guarantee (_owner != Self, "invariant");
   return save;
}

7、總結

     ObjectMonitor維護了三個ObjectWaiter鏈表,分別是cxq鏈表、EntryList鏈表和WaitSet鏈表,對應鏈表中ObjectWaiter的狀態分別是TS_CXQ,TS_ENTER和TS_WAIT。調用enter方法時,如果自旋獲取鎖失敗就會創建一個ObjectWaiter並加入到cxq鏈表中,某個已經獲取鎖的線程調用wait方法會創建一個ObjectWaiter並加入到WaitSet鏈表中,當某個線程調用notify/notifyAll方法“喚醒”該線程時,會將該ObjectWaiter從WaitSet鏈表中移除然後加入到cxq鏈表頭。當某個獲取鎖的線程釋放鎖時,就會喚醒EntryList鏈表頭對應的線程,如果EntryList鏈表爲空,則將此時的cxq鏈表中的元素整體轉移到EntryList鏈表中,然後同樣的喚醒EntryList鏈表頭對應的線程,被喚醒後該線程一樣調用enter方法搶佔鎖。

    

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