您的位置:首页 > 编程语言 > Java开发

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

2011-06-08 22:30 513 查看
在oracle JVM 1.6 里面实现的object的wait 和notify方法是在synchronizer.cpp里实现。

先介绍2个对象:

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

在synchronizer.cpp 里定义了,ObjectMonitor 的对象,我们来看ObjectMonitor的对象的结构体

ObjectMonitor::ObjectMonitor() {
_header       = NULL;
_count        = 0;
_waiters      = 0,
_recursions   = 0;
_object       = NULL;
_owner        = NULL;
_WaitSet      = NULL;
_WaitSetLock  = 0 ;
_Responsible  = NULL ;
_succ         = NULL ;
_cxq          = NULL ;
FreeNext      = NULL ;
_EntryList    = NULL ;
_SpinFreq     = 0 ;
_SpinClock    = 0 ;
OwnerIsThread = 0 ;
}


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

建立ObjectMonitor的算法:

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

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

2. ObjectWaiter 对象

ObjectWaiter 对象

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;
ParkEvent *   _event;
volatile int  _notified ;
volatile TStates TState ;
Sorted        _Sorted ;           // List placement disposition
bool          _active ;           // Contention monitoring is enabled
public:
ObjectWaiter(Thread* thread) {
_next     = NULL;
_prev     = NULL;
_notified = 0;
TState    = TS_RUN ;
_thread   = thread;
_event    = thread->_ParkEvent ;
_active   = false;
assert (_event != NULL, "invariant") ;
}
void wait_reenter_begin(ObjectMonitor *mon) {
JavaThread *jt = (JavaThread *)this->_thread;
_active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
}
void wait_reenter_end(ObjectMonitor *mon) {
JavaThread *jt = (JavaThread *)this->_thread;
JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
}
};


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方法里
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: