Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。
微信小程序「猿面试」每日分享一道大厂面试题,涉及 Java、Android、鸿蒙和ArkTS、设计模式、算法和数据结构 等内容。
你是如何使用 wait () 方法的?使用 if 还是 while
在 Java 中,wait() 方法通常与 synchronized 关键字一起使用,以确保线程之间的正确同步。wait() 方法使当前线程进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法来唤醒它。
在 Java 并发编程中,wait() 方法通常放在 while 循环中而不是 if 语句中,这种做法主要是为了解决下面的问题:
- 防止虚假唤醒
- 确保线程被唤醒时满足条件,避免因条件变化导致线程继续执行错误的操作
什么是虚假唤醒(spurious wakeups)
虚假唤醒是指线程在没有被显式唤醒(例如通过 notify() 或 notifyAll())的情况下,仍然从 wait() 状态中恢复执行的现象。
这种情况可能因为操作系统的线程调度或其他线程的干扰而发生。如果 wait() 方法放在 if 语句中,一旦线程被虚假唤醒,它可能会在没有获得锁的情况下退出循环,从而导致程序逻辑错误。
使用 while 循环的原因
防止虚假唤醒
Java 中的 wait() 方法可能会出现“虚假唤醒”现象,即线程在没有被其他线程调用 notify() 或 notifyAll() 的情况下被唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。
为了避免这种情况,可以将 wait() 放在 while 循环中,每次从 wait() 方法返回后,都需要重新检查条件是否满足,这样可以确保线程在等待条件未满足前,会持续等待。
即使线程因为虚假唤醒而提前醒来,循环会继续检查条件,如果条件不满足,线程会再次调用 wait() 方法,从而避免虚假唤醒对程序逻辑的影响。
使用 while 循环可以确保在每次从 wait() 方法返回后,都会重新检查条件是否满足,从而避免因虚假唤醒而导致的错误。以下是一个典型的使用场景:
synchronized (monitor) {
while (!condition) {
try {
monitor.wait();
} catch (InterruptedException e) {
// 处理中断异常
}
}
// 条件满足,继续执行
}
在这个例子中,monitor 是一个对象,condition 是一个布尔条件。
线程在进入 synchronized 块后,会检查 condition 是否为 true。如果条件不满足,线程会调用 monitor.wait() 进入等待状态,并释放锁。
当其他线程调用 monitor.notify() 或 monitor.notifyAll() 时,等待的线程会被唤醒,并重新进入 synchronized 块。此时,线程会再次检查 condition,只有在条件满足的情况下才会继续执行。
确保条件满足
当线程被唤醒时,它需要重新检查等待的条件是否仍然满足。如果条件不满足,线程应该再次进入等待状态。
通过在 while 循环中调用 wait(),可以确保线程在每次唤醒后都重新检查条件,从而避免因条件变化而导致的错误行为。
避免条件变化
在多线程环境中,其他线程可能会在当前线程进入等待状态后修改条件。如果 wait() 方法放在 if 语句中,当线程被唤醒时,可能无法及时检测到条件的变化,从而导致线程继续执行错误的操作。
更多大厂面试题,欢迎前往微信搜索小程序 「猿面试」 查看。微信小程序 (猿面试) 包含了 Java、Android、鸿蒙和ArkTS、设计模式、算法和数据结构 相关内容,
Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。
更多面试题: