无论是面试还是日常开发过程中,我们总是绕不开sleep和wait的区别,尤其是搞服务端开发的童鞋。今天偶尔遇到这个问题,大概总结如下:
一、归属类
1.sleep是Thread类的静态方法,且有重载兄弟
image.png
2.wait是Object对象实例的公共方法,也有重载兄弟
image.png
结论:Thread#sleep是类锁,object#wait是对象锁。注意:一个类可以有很多对象锁,但只有能有一个类锁。
二、定义
- Thread#sleep一旦执行,当前线程立即睡眠一段时间,其精度受系统定时器和协调器控制。时间一到立马苏醒。在睡眠的这段时间,它不会释放自己持有的控制权,也就是锁和资源。看看人家的定义英文版:
* Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does not lose ownership of any monitors.
- Object#wait方法引起当前线程去等待通知,通知类型包括:其他线程调用notify或notifyAll方法;或者规定的时间到了。看看英文版定义:
* Causes the current thread to wait until either another thread invokes the * {@link java.lang.Object#notify()} method or the * {@link java.lang.Object#notifyAll()} method for this object, or a * specified amount of time has elapsed.
我看到这个定义是蒙圈的:
1.wait到底在等待什么?
2.for this object到底是哪个对象?
3.规定的时间到底是多久?
庆幸的的是Google怕我看不懂,做了扩展解释。
调用wait时,当前线程会被放入到wait set(等待集)里,这个等待集是针对指定的某个object对象的。而且等待集里的线程,会放弃任何针对这个object对象的synchronized同步请求。线程对自己的调度请求无效并保持休眠状态。直到某个条件发生!英文如下:
* This method causes the current thread (call it <var>T</var>) to * place itself in the wait set for this object and then to relinquish * any and all synchronization claims on this object. Thread <var>T</var> * becomes disabled for thread scheduling purposes and lies dormant * until one of four things happens:
这样我就明白了,wait是在等待从等待集出来,而且等待集是与某个对象object对应的。在等待期间,等待集里的线程不参与同步请求,也就是不竞争资源。关于某个对象,还还记得synchronized怎么玩吗?
* synchronized (obj) { * while (<condition does not hold>) * obj.wait(timeout); * ... // Perform action appropriate to condition * }
针对同一个对象obj的锁去竞争,才能产生所谓的同步。for this object 也就是我们自己定义的共有锁对象,大家一起去排队抢锁。
针对第3点,其实wait已经被调用了,除了notify、notifyAll、Thread#interrupt三种情况,可以把等待集wait set中的线程释放出来,也就是唤醒之外,还有一种情况就是针对传入的object#wait(long millis)方法中的参数,时间到了当前线程自然要释放。
至此,以上三个问题全明白了。
结论:Thread#sleep方法持有的是类锁,控制权始终属于Thread这个类本身,那么无论任何线程调用Thread#sleep方法,自己都可以随时休息或者暂停执行,大权还在自己手里。而object#wait方法持有的是对象锁,一把锁可以由多个对象进行竞争,只有拿到锁的对象所在线程可以拥有控制权,也就是拥有了资源控制权。而执行了object#wait方法的线程,自然就放入等待集,失去了同步锁竞争权。
所以,Thead#sleep和object#wait的区别,本质上还是类锁和对象锁的区别。正因为object#wait持有的是对象锁,它需要对多个锁进行处理,面对的情况比较复杂。这才在面试中被面试官经常拿出来虐人。其实我还想说一句:
都是千年的狐狸,玩什么聊斋啊!
网友评论