java 中的 wait 和 notify 实现的源码分析

原文:https://blog.csdn.net/raintungli/article/details/6532784


在oracle JVM 1.6 里面实现的object的wait 和notify方法是在synchronizer.cpp里实现。 

先介绍2个对象:

1. ObjectMonitor  对象 主要用来监视创立的Object 

在synchronizer.cpp 里定义了,ObjectMonitor 的对象,我们来看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. }  

每个object的对象里 markOop->monitor() 里可以保存ObjectMonitor的对象。

 

建立ObjectMonitor的算法:

如果不存在,可以向Thread 的ObjectMonitor 的对象列表中Allocate free 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方法

 

调用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方法里

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值