美文网首页
【进阶】 wait sleep

【进阶】 wait sleep

作者: lconcise | 来源:发表于2021-08-05 08:08 被阅读0次
    • wait sleep 区别

    不同:

    1. wait会释放锁,而sleep不会释放锁
    2. wait只能在同步方法和同步代码块中使用,而sleep任何地方都可以

    相同点:都会让渡CPU执行时间,等待再次调度

    • wait为什么要在同步块中使用?

    1. lost wake up 问题

    如果wait 不在同步方法或者同步代码块中使用,运行代码会直接报错。

        public static void main(String[] args) throws Exception{
            Object obj = new Object();
            obj.wait();
        }
    
    Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:502)
        at top.lconcise.practice.demo.NodeDemo.main(NodeDemo.java:11)
    

    事情得从一个多线程编程里面臭名昭著的问题"Lost wake-up problem"说起。

    这个问题并不是说只在Java语言中会出现,而是会在所有的多线程环境下出现。

    生产者消费之的代码:
    生产者伪代码:

    count+1;
    notify();
    

    消费者伪代码:

    while(count<=0){
       wait()
    }
    count--
    
    image.png

    解决该问题,就需要保证这一系列操作的原子性,在同步方法或同步代码中执行,可以保证原子性。

    2. wait notify 原理

    1. 调用wait() 首先会获取监视器锁,获得成功后,会让线程进入等待状态进入等待队列并且释放锁;
    2. 然后当其他线程调用notify或者notifyall以后,会选择从等待队列中唤醒任意一个线程
    3. 而执行完notify方法以后,并不会立马唤醒线程,原因是当前线程仍然持有这把锁,处于等待状态的线程无法获得锁。必须要等到当前的线程执行完按monitorexit指令之后,也就是被释放之后,处于等待队列的线程就可以开始竞争锁了。

    所以 wait 方法要做两件事

    1. 释放当前对象的锁
    2. 使得当前线程进入阻塞队列
      而这些操作都和监视器是相关的,所以wait必须要获得一个监视器锁,只在synchronized里面,才能明确锁。
    • 为什么sleep 不用在同步代码块中?

    放在同步块中是为了多线程并发处理,大家按照顺序依次合理干活,不要造成死锁饥饿现象,但是sleep()方法就是想让当前线程进入阻塞状态,不要干活,我也不释放我已经拥有的锁,等到sleep()的时间到了,我再进入就绪态,等待cpu派活给我。sleep根本就不存在多线程并发访问问题,所以就不需要放在同步块中。

    • 为什么wait方法在object类中,sleep方法在Thread类中?

    wait方法是让当前线程释放锁。然后让别的线程继续竞争。阻塞线程
    notify通知 唤醒一个阻塞的线程 随机通知一个
    这些都应该属于资源锁的动作,而作为锁,java中锁一般锁谁?锁的是对象,因为对象是资源,是我们需要操作的实体,而Object是所有对象的父类

    sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定。

    https://www.cnblogs.com/myseries/p/13903051.html

    相关文章

      网友评论

          本文标题:【进阶】 wait sleep

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