java wait 和notify實現源碼

先介紹2個對象:

1. ObjectMonitor  對象 主要用來監視創立的Object 

在synchronizer.cpp 裏定義了,ObjectMonitor 的對象,我們來看ObjectMonitor的對象的結構體

  1. ObjectMonitor::ObjectMonitor() {  
  2.   _header       = NULL;  
  3.   _count        = 0;  
  4.   _waiters      = 0,  
  5.   _recursions   = 0;  
  6.   _object       = NULL;  
  7.   _owner        = NULL;  
  8.   _WaitSet      = NULL;  
  9.   _WaitSetLock  = 0 ;  
  10.   _Responsible  = NULL ;  
  11.   _succ         = NULL ;  
  12.   _cxq          = NULL ;  
  13.   FreeNext      = NULL ;  
  14.   _EntryList    = NULL ;  
  15.   _SpinFreq     = 0 ;  
  16.   _SpinClock    = 0 ;  
  17.   OwnerIsThread = 0 ;  
  18. }  

每個object的對象裏 markOop->monitor() 裏可以保存ObjectMonitor的對象。

 

建立ObjectMonitor的算法:

如果不存在,可以向Thread 的ObjectMonitor 的對象列表中Allocate free objectMonitor 對象。 

每個線程都有ObjectMonitor 的free和used的objectMonitor對象列表,如果沒有free objectMonitor對象列表,將向global 中ListLock Allocate爲了提高效率。

 

2.  ObjectWaiter 對象

 

 ObjectWaiter 對象

  1. class ObjectWaiter : public StackObj {  
  2.  public:  
  3.   enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;  
  4.   enum Sorted  { PREPEND, APPEND, SORTED } ;  
  5.   ObjectWaiter * volatile _next;  
  6.   ObjectWaiter * volatile _prev;  
  7.   Thread*       _thread;  
  8.   ParkEvent *   _event;  
  9.   volatile int  _notified ;  
  10.   volatile TStates TState ;  
  11.   Sorted        _Sorted ;           // List placement disposition  
  12.   bool          _active ;           // Contention monitoring is enabled  
  13.  public:  
  14.   ObjectWaiter(Thread* thread) {  
  15.     _next     = NULL;  
  16.     _prev     = NULL;  
  17.     _notified = 0;  
  18.     TState    = TS_RUN ;  
  19.     _thread   = thread;  
  20.     _event    = thread->_ParkEvent ;  
  21.     _active   = false;  
  22.     assert (_event != NULL, "invariant") ;  
  23.   }  
  24.   void wait_reenter_begin(ObjectMonitor *mon) {  
  25.     JavaThread *jt = (JavaThread *)this->_thread;  
  26.     _active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);  
  27.   }  
  28.   void wait_reenter_end(ObjectMonitor *mon) {  
  29.     JavaThread *jt = (JavaThread *)this->_thread;  
  30.     JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);  
  31.   }  
  32. };  

 

ObjectWaiter 對象裏存放thread(線程對象) 和 ParkEvent(線程的unpark), 每一個等待鎖的線程都會有一個ObjectWaiter對象.

而objectwaiter是個雙向鏈表結構的對象。

 

我們可以看到在ObjectMonitor對象裏有2個隊列成員_WaitSet 和 _EntryList 存放的就是ObjectWaiter

 

_WaitSet:

主要存放所有wait的線程的對象,也就是說如果有線程處於wait狀態,將被掛入這個隊列

 

_EntryList:

所有在等待獲取鎖的線程的對象,也就是說如果有線程處於等待獲取鎖的狀態的時候,將被掛入這個隊列。

 

Wait 方法實現:

 

ObjectSynchronizer::wait方法

通過object的對象中找到ObjectMonitor對象

調用方法 

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS)

 

通過ObjectMonitor::AddWaiter調用把新建立的ObjectWaiter對象放入到 _WaitSet 的隊列的末尾中

然後在ObjectMonitor::exit釋放鎖,接着 thread_ParkEvent->park  也就是wait

 

 

Notify方法的實現:

 

ObjectSynchronizer::notify方法

 

調用ObjectSynchronizer::inflate

object的對象中找到ObjectMonitor對象 

 

然後調用方法ObjectMonitor::notify

 

調用ObjectMonitor::DequeueWaiter 摘除第一個ObjectWaiter對象從_WaitSet 的隊列中

並把這個ObjectWaiter對象放入_EntryList中,_EntryList 存放的是ObjectWaiter的對象列表,列表的大小就是那些所有在等待這個對象鎖的線程數。

注意這裏並沒有調用ObjectMonitor::exit釋放鎖

 

NotifyALL和Notify 的區別就是

 

通過遍歷調用ObjectMonitor::DequeueWaiter,把所有的_WaitSet的隊列中的ObjectWaiter對象放入到_EntryList中

 

關於放入到_EntryList的策略大概有4中Policy,其中還涉及到一個_cxq的隊列,先不具體介紹了

 

notify, 和notifyAll 都沒有釋放對象的鎖,而是在Synchronizer同步塊結束的時候釋放

 

如何釋放鎖

調用ObjectMonitor::exit

從_EntryList裏找到一個ObjectWaiter,因爲ObjectWaiter裏有線程的_event ParkEvent,調用unpark() 通知ObjectWaite裏的線程運行(拿到鎖),具體實現在ObjectMonitor::ExitEpilog方法裏

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