Source code analysis of wait and notify implementation in java

Original: https://blog.csdn.net/raintungli/article/details/6532784


The wait and notify methods of object implemented in oracle JVM 1.6 are implemented in synchronizer.cpp. 

First introduce two objects:

1. The ObjectMonitor object is mainly used to monitor the created Object 

Defined in synchronizer.cpp, the object of ObjectMonitor, let's look at the structure of the object of ObjectMonitor

[cpp]  view plain  copy
  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. }  

The object of ObjectMonitor can be saved in markOop->monitor() of each object.

 

Algorithm to build ObjectMonitor:

If it does not exist, you can Allocate free objectMonitor object to the object list of Thread's ObjectMonitor. 

每个线程都有ObjectMonitor 的free和used的objectMonitor对象列表,如果没有free objectMonitor对象列表,将向global 中ListLock Allocate为了提高效率。

 

2.  ObjectWaiter 对象

 

 ObjectWaiter 对象

[cpp]  view plain  copy
  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方法

 

Call ObjectSynchronizer::inflate

ObjectMonitor object is found in the object of object 

 

Then call the method ObjectMonitor::notify

 

Call ObjectMonitor::DequeueWaiter to dequeue the first ObjectWaiter object from the queue in _WaitSet

And put this ObjectWaiter object into _EntryList, _EntryList stores the object list of ObjectWaiter, and the size of the list is the number of threads waiting for this object lock.

Note that ObjectMonitor::exit is not called to release the lock

 

The difference between NotifyALL and Notify is that

 

By traversing and calling ObjectMonitor::DequeueWaiter, put all ObjectWaiter objects in the queue of _WaitSet into _EntryList

 

There are about 4 policies for putting into _EntryList, which also involves a _cxq queue, which will not be introduced in detail.

 

notify, and notifyAll do not release the object's lock, but release it at the end of the Synchronizer synchronization block

 

How to release the lock

call ObjectMonitor::exit

Find an ObjectWaiter from _EntryList, because ObjectWaiter has a thread's _event ParkEvent, call unpark() to notify the thread in ObjectWaite to run (get the lock), which is implemented in the ObjectMonitor::ExitEpilog method

 


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326029009&siteId=291194637