wait/notify,sleep方法

wait/notify源码

wait是用来让线程等待的,并且释放锁。

notify是用来唤醒等待线程的,执行完后,在同一同步队列中的等待线程开始抢占锁。

监视器: monitor
锁: lock(JVM里只有一种独占方式的lock)
进入监视器: monitorenter
离开/释放监视器: monitorexit
(monitorenter和monitorexit是JVM的指令)
拥有者: owner

通过synchronized来完成的,使用了monitorenter指令和monitorexit指令

monitor使用了ObjectMonitor来实现。

JAVA程序中每一个监视区域都和一个对象引用相关联。

锁住一个对象相当于获得对象相关联的监视器

这里的监视器可以比喻成一个房间,进入房间相当于进入监视器,占据房间相当于持有监视器,离开房间相当于释放监视器。

wait/notify,sleep方法

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

在上图中可以看见成员里头有2个队列:_WaitSet和_EntryList(保存ObjectWaiter对象列表);_owner执向获得ObjectMonitor对象的线程。看图

wait/notify,sleep方法

_WaitSet :处于wait状态的线程,会被加入到wait set;
_EntryList:处于等待锁block状态的线程,会被加入到entry set;
ObjectWaiter对象是双向链表结构,保存了_thread(当前线程)以及当前的状态TState等数据, 每个等待锁的线程都会被封装成ObjectWaiter对象,然后加入不同的队列中去。

wait方法实现

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

notify方法实现

  1. 如果当前_WaitSet为空,即没有正在等待的线程,则直接返回;
  2. 通过ObjectMonitor :: DequeueWaiter方法,获取_WaitSet列表中的第一个ObjectWaiter节点,实现很简单。

notifyAll方法实现

跟notify差不多,就是第二步直接用for循环取出所有的_WaitSet中的节点。

wait/notify,sleep方法

对于java中的sleep实现

我想,应该是和LinuxC下的sleep类似的。。。肯定不一样
通过底层alarm设定闹钟,闹钟会发信号给这个线程。 sleep是不会释放锁的。
sleep是Thread中的静态方法。