Object.wait和Object.notify实现
Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait()
和notify()
方法的实现多线程协作提供了保证。
ObjectMonitor
在HotSpot虚拟机中,monitor
采用ObjectMonitor
实现。
ObjectMonitor
对象中有两个队列:_WaitSet 和 _EntryList,用来保存ObjectWaiter
对象列表;_owner指向获得ObjectMonitor
对象的线程。
_WaitSet
:处于wait状态的线程,会被加入到wait set;_EntryList
:处于等待锁block状态的线程,会被加入到entry list;
ObjectWaiter
ObjectWaiter
对象是双向链表结构,保存了_thread(当前线程)以及当前的状态TState等数据, 每个等待锁的线程都会被封装成ObjectWaiter
对象。
wait方法实现
lock.wait()
方法最终通过ObjectMonitor
的void wait(jlong millis, bool interruptable, TRAPS)
;
实现过程:
- 1、将当前线程封装成
ObjectWaiter
对象node; - 2、通过
ObjectMonitor::AddWaiter
方法将node添加到_WaitSet
列表中; - 3、通过
ObjectMonitor::exit
方法释放当前的ObjectMonitor
对象,这样其它竞争线程就可以获取该ObjectMonitor
对象。 - 4、最终底层的
park()
方法会挂起线程;
notify方法实现
lock.notify()
方法最终通过ObjectMonitor
的void notify(TRAPS)
实现。
- 1、如果当前
_WaitSet
为空,即没有正在等待的线程,则直接返回; - 2、通过
ObjectMonitor::DequeueWaiter
方法,获取_WaitSet
列表中的第一个ObjectWaiter
节点,实现也很简单。这里需要注意的是,在jdk的notify()
方法注释是随机唤醒一个线程,其实是第一个ObjectWaiter
节点。 - 3、根据不同的策略,将取出来的
ObjectWaiter
节点,加入到_EntryList
或则通过Atomic::cmpxchg_ptr
指令进行自旋操作cxq
notifyAll方法实现
lock.notifyAll()
方法最终通过ObjectMonitor
的void notifyAll(TRAPS)
实现:
通过for循环取出_WaitSet
的ObjectWaiter
节点,并根据不同策略,加入到_EntryList
或则进行自旋操作。