Java多线程-03丨Object.wait和Object.notify实现

Posted by jiefang on October 28, 2019

Object.wait和Object.notify实现

Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait()notify()方法的实现多线程协作提供了保证。

ObjectMonitor

在HotSpot虚拟机中,monitor采用ObjectMonitor实现。

ObjectMonitor结构

ObjectMonitor对象中有两个队列:_WaitSet_EntryList,用来保存ObjectWaiter对象列表;_owner指向获得ObjectMonitor对象的线程。

Monitor Object 模式

  • _WaitSet :处于wait状态的线程,会被加入到wait set;
  • _EntryList:处于等待锁block状态的线程,会被加入到entry list;

ObjectWaiter

ObjectWaiter对象是双向链表结构,保存了_thread(当前线程)以及当前的状态TState等数据, 每个等待锁的线程都会被封装成ObjectWaiter对象。

ObjectWaiter

wait方法实现

lock.wait()方法最终通过ObjectMonitorvoid wait(jlong millis, bool interruptable, TRAPS);

实现过程:

  • 1、将当前线程封装成ObjectWaiter对象node;
  • 2、通过ObjectMonitor::AddWaiter方法将node添加到_WaitSet列表中;
  • 3、通过ObjectMonitor::exit方法释放当前的ObjectMonitor对象,这样其它竞争线程就可以获取该ObjectMonitor对象。
  • 4、最终底层的park()方法会挂起线程;

notify方法实现

lock.notify()方法最终通过ObjectMonitorvoid notify(TRAPS)实现。

  • 1、如果当前_WaitSet为空,即没有正在等待的线程,则直接返回;
  • 2、通过ObjectMonitor::DequeueWaiter方法,获取_WaitSet列表中的第一个ObjectWaiter节点,实现也很简单。这里需要注意的是,在jdk的notify()方法注释是随机唤醒一个线程,其实是第一个ObjectWaiter节点。
  • 3、根据不同的策略,将取出来的ObjectWaiter节点,加入到_EntryList或则通过Atomic::cmpxchg_ptr指令进行自旋操作cxq

notifyAll方法实现

lock.notifyAll()方法最终通过ObjectMonitorvoid notifyAll(TRAPS)实现: 通过for循环取出_WaitSetObjectWaiter节点,并根据不同策略,加入到_EntryList或则进行自旋操作。