线程饥饿

线程饥饿:某个线程长期无法获得所需的资源(通常是锁),导致一直无法执行的情况

=====================================================

上述情况我们就可以使用  wait 和 notify 了;

  1. 小绿人(线程 A)抢到锁,进厕所(执行同步块);

  2. 小绿人解决完,主动调用wait()(进入阻塞)

    • 释放厕所的锁(把钥匙交出来);

    • 自己进入 “厕所的等待队列”(到队伍最后排队);

  3. 其他人(线程 B/C)可以抢到锁,进厕所;

  4. 其他人用完厕所,调用notify()(解除阻塞)

    • 从等待队列里唤醒一个线程(比如小绿人);

    • 小绿人被唤醒后,重新去竞争锁(排队抢钥匙)

=================================================

join与 wait的区别

join 时等待另一个线程执行完,才继续执行;

wait则是等待另一个线程通过 notify 通知才继续执行(不要求执行完);

====================================================

调用 wait 对象必须和synchronized 的锁对象是一致的,因此 wait 解锁必然是解的 object的 锁;当wait 被唤醒后,重新获取到的还是 object的锁;

notify也是一样的;

--------------------------------------------------------------------------------------

==============================================

wait,join,sleep;都有可能会被 interrupt唤醒;

注意:要将 sleep 写到 synchronized 外面,否则,由于 t1 t2 执行顺序不确定,就可能会 t2 先拿到锁,此时 t1 就没执行到 wait ; t2 就会先执行 notify 结果不符合预期(需要确保,代码时先执行 wait ,后执行notify;虽然先 notify 不会出现异常,但是 wait 就无法被唤醒,逻辑上存在问题)

线程 t1 启动 就会调用 wait 进入阻塞等待; 线程t2 在启动时,会先sleep 时间到了之后,在进行 notify 唤醒 t1;

上述代码执行过程:

1. t1 执行后,会先拿到锁,并且打印(t1 wait 前),并进入 wait 方法(释放锁 +阻塞)

2.t2 执行后,会先 sleep(这个sleep 就可以让 t1 先拿到 锁)

3.t2 sleep 结束后,由于 t1 是 wait 状态,锁是释放的,t2 就能拿到 锁;接下来打印(t2 notify 之前),执行 notify 操作,这个操作就能唤醒 t1 (此时 t1 就从 WIAITING 状态恢复)

4. 但是由于 t2 还未释放锁,t1 恢复后,处于尝试获取锁的状态,就出现了阻塞状态(BOLKED)

5.t2 执行结束后,t2 notify 后释放锁,t2 执行完毕;t1 的 wait 就可以重新获取到锁,继续打印(t1 wait 后);

=======================================================

wait():持锁时临时让渡资

源线程在synchronized块内调用wait(),会释放锁、进入等待队列、暂停执行(保留 “继续执行的资格”)。

锁释放的两种场景

wait():块内中途临时释放,不退出块;

出synchronized块:执行完代码后自动释放。

执行位置:JVM 自动管理

wait()时 JVM 保存执行上下文,唤醒后从wait()下一行继续执行。

====================================================

wait 其他要点

1.wait 其他要点提供了两个版本;

2.wait 和 notify 彼此之间是通过 object 对象联系起来的;

object1.wait()

object2.notify();

这种是无法通过 notify 唤醒的,必须是一致的对象才可以;

3.notifyAll 唤醒这个对象(锁对象)上所有等待的线程;(更倾向于使用 notify)

假设有多个线程,都是用同一个对象 lock;

针对这个(锁对象) 进行notifyAll 此时就会全部唤醒,进入抢占;

===================================================

wait 和 sleep 的区别

1.wait 和 sleep 都有 带指定时间解除 阻塞;

2.wait 和 sleep 都可以被提前唤醒

wait 是通过 notify;

sleep 是通过 interrupt;(是通过异常的方式提前还行;正常业务都不使用这个;只有在特殊情况才会使用;)

使用 wait 的场景:不知道要等待多长时间;

使用 sleep 的场景:知道要等待多长时间才使用;

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐