wait、notify、sleep 与 线程饥饿问题
注意:要将 sleep 写到 synchronized 外面,否则,由于 t1 t2 执行顺序不确定,就可能会 t2 先拿到锁,此时 t1 就没执行到 wait;t2 就会先执行 notify 结果不符合预期(需要确保,代码时先执行 wait ,后执行notify;3.t2 sleep 结束后,由于 t1 是 wait 状态,锁是释放的,t2 就能拿到 锁;t1 执行后,会先拿到锁,并且打印(t1
线程饥饿

线程饥饿:某个线程长期无法获得所需的资源(通常是锁),导致一直无法执行的情况
=====================================================
上述情况我们就可以使用 wait 和 notify 了;
-
小绿人(线程 A)抢到锁,进厕所(执行同步块);
-
小绿人解决完,主动调用
wait()(进入阻塞)-
释放厕所的锁(把钥匙交出来);
-
自己进入 “厕所的等待队列”(到队伍最后排队);
-
-
其他人(线程 B/C)可以抢到锁,进厕所;
-
其他人用完厕所,调用
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 的场景:知道要等待多长时间才使用;
更多推荐


所有评论(0)