文章目录
1. API概述
以下四个方法都是操作「当前对象obj对应的Monitor对象(之后简称当前对象锁)」中的 Owner 或 WaitSet。
这些方法执行的前提都是当前线程必须持有锁。
| 方法签名 | 功能概述 | 备注 |
|---|---|---|
| void Object.wait() | 使当前对象锁中Owner进入WAITING状态 | 当前线程必须要持有锁 |
| void Object.wait(long m) | 使当前对象锁中Owner进入TIMED_WAITING状态 | 当前线程必须要持有锁,m毫秒后会自动唤醒 |
| void Object.notify( ) | 唤醒当前对象锁中WaiSet的随机一个线程 | 当前线程必须要持有锁 |
| void Object.notifyAll( ) | 唤醒当前对象锁中WaiSet的所有线程 | 当前线程必须要持有锁 |
2. obj.wait( ) / obj.wait( long m ) 底层原理:
- [释放锁并进入WaitSet]调用obj.wait( )/obj.wait( long m )后,当前对象锁的 Owner 将进入 WaitSet 并进入「WAITING/TIMED_WAITING」状态,此时 Owner 空缺,因此释放了锁;
- [唤醒EntryList的阻塞线程]由于 Owner 空缺,根据JVM底层算法,某个EntryList中的线程将被唤醒,并成为新的Owner。

3. 唤醒 WAITING / TIMED_WAITING 线程的三种方式
处于WaitSet的线程会在三种情况下会被唤醒,进入到 EntryList 并进入 BLOCKED 状态:
- [自动唤醒]若线程因调用了obj.wait( long m )而进入了TIME_WAITING状态,会在m毫秒后被自动唤醒;
- [随机唤醒]在调用obj.notify( )后,JVM会将WaitSet中 随机一个线程唤醒;
- [全部唤醒]在调用obj.notifyAll( )后,JVM会将WaitSet的所有线程唤醒。

4. Thread.sleep( long m ) VS obj.wait( long m )
4.1. 相同点
- [状态一致、自动唤醒]sleep( long m )与wait( long m )调用后,二者的状态都是TIMED_WAITING,m毫秒后将被自动唤醒;
- [被打断后均会抛出异常]处于TIMED_WAITING(和WAITING)状态的线程被打断后都会抛出异常,并将标识重置为false。
4.2. 不同点
- [静态vs非静态]Thread.sleep( long m )是一个静态方法,而obj.wait( long m)是Object类的成员方法,这意味着这个obj对应的 Monitor 对象必须要有 Owner;
- [是否释放锁]sleep( long m )调用后仍为Owner(不释放锁),wait( long m )调用后则是让自己从 Owner 进入到 WaitSet(释放了锁);
- [wait有无参方法]无参方法wait( )调用后将进入WAITING状态,只能被打断或被nodify( ) / nodifyAll( )唤醒;
参考资料
版权声明:本文为xyxyxyxyxyxyx原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。