wait/notify,sleep方法
wait/notify源码
wait是用来让线程等待的,并且释放锁。
notify是用来唤醒等待线程的,执行完后,在同一同步队列中的等待线程开始抢占锁。
监视器: monitor
锁: lock(JVM里只有一种独占方式的lock)
进入监视器: monitorenter
离开/释放监视器: monitorexit
(monitorenter和monitorexit是JVM的指令)
拥有者: owner
通过synchronized来完成的,使用了monitorenter
指令和monitorexit
指令
monitor使用了ObjectMonitor来实现。
JAVA程序中每一个监视区域都和一个对象引用相关联。
锁住一个对象相当于获得对象相关联的监视器
这里的监视器可以比喻成一个房间,进入房间相当于进入监视器,占据房间相当于持有监视器,离开房间相当于释放监视器。
每个线程都有ObjectMonitor 的free和used的objectMonitor对象列表,如果没有free objectMonitor对象列表,将向global 中ListLock Allocate为了提高效率
在上图中可以看见成员里头有2个队列:_WaitSet和_EntryList(保存ObjectWaiter对象列表);_owner执向获得ObjectMonitor对象的线程。看图
_WaitSet :处于wait状态的线程,会被加入到wait set;
_EntryList:处于等待锁block状态的线程,会被加入到entry set;
ObjectWaiter对象是双向链表结构,保存了_thread(当前线程)以及当前的状态TState等数据, 每个等待锁的线程都会被封装成ObjectWaiter对象,然后加入不同的队列中去。
wait方法实现
- 将当前线程封装成
ObjectWaiter
对象->node
; - 通过
ObjectMonitor :: AddWaiter
方法将node添加到_WaitSet
列表中; - 通过
ObjectMonitor :: exit
方法释放当前的ObjectMonitor
对象,这样其它竞争线程就可以获取该ObjectMonitor
对象。 - 最终底层的park方法会挂起线程。
notify方法实现
- 如果当前
_WaitSet
为空,即没有正在等待的线程,则直接返回; - 通过
ObjectMonitor :: DequeueWaiter
方法,获取_WaitSet
列表中的第一个ObjectWaiter
节点,实现很简单。
notifyAll方法实现
跟notify差不多,就是第二步直接用for循环取出所有的_WaitSet
中的节点。
对于java中的sleep实现
我想,应该是和LinuxC下的sleep类似的。。。肯定不一样
通过底层alarm设定闹钟,闹钟会发信号给这个线程。 sleep是不会释放锁的。
sleep是Thread中的静态方法。