美文网首页
sleep和wait区别太难了

sleep和wait区别太难了

作者: 小天使999999 | 来源:发表于2020-05-27 19:09 被阅读0次

    无论是面试还是日常开发过程中,我们总是绕不开sleep和wait的区别,尤其是搞服务端开发的童鞋。今天偶尔遇到这个问题,大概总结如下:

    一、归属类

    1.sleep是Thread类的静态方法,且有重载兄弟


    image.png

    2.wait是Object对象实例的公共方法,也有重载兄弟


    image.png

    结论:Thread#sleep是类锁,object#wait是对象锁。注意:一个类可以有很多对象锁,但只有能有一个类锁。

    二、定义

    1. 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.
    
    1. 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 (&lt;condition does not hold&gt;)
    *             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持有的是对象锁,它需要对多个锁进行处理,面对的情况比较复杂。这才在面试中被面试官经常拿出来虐人。其实我还想说一句:

    都是千年的狐狸,玩什么聊斋啊!

    相关文章

      网友评论

          本文标题:sleep和wait区别太难了

          本文链接:https://www.haomeiwen.com/subject/cwewahtx.html