Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。
来自微信小程序「猿面试」每日分享一道大厂面试题,涉及 Java、Android、鸿蒙和ArkTS、设计模式、算法和数据结构 等内容。
wait 和 notify 为什么要放在 synchronized 代码块中?
wait() 和 notify() / notifyAll() 是 Java 中用于线程间通信的方法,它们必须在 synchronized 代码块或方法中使用,原因主要有以下几点:
监视器规则
Java 规定,wait() 和 notify() 必须在拥有对象监视器的线程中调用。换句话说,调用这些方法的线程必须首先获得对象的锁(通过 synchronized)。
如果线程没有持有对象的锁,调用 wait() 将会抛出 IllegalMonitorStateException 异常,因此,必须在同步代码块中调用这些方法,以确保当前线程持有正确的锁
线程安全
wait() 和 notify() 必然是成对出现的,如果一个线程被 wait() 方法阻塞,那么必然需要通过 notify() 方法来唤醒这个被阻塞的线程,从而实现多线程之间的通信。
因此需要保证 wait() 和 notify() 操作需要保证原子性,即在同一时刻只能有一个线程执行这些操作。synchronized 关键字确保了这一点,因为它会锁定对象或类的监视器,防止多个线程同时进入临界区。
如果不在同步代码块中,多个线程可能会同时调用 wait() 或 notify(),导致不可预测的行为和数据不一致。
避免 lost wake up 问题
Java 强制要求 wait() 和 notify() 必须在同步块中调用,以避免 lost wake up 问题。这种问题发生在多个线程竞争同一个锁时,可能会导致某些线程的唤醒信号丢失。
锁的管理:
wait() 和 notify() 方法需要操作对象的监视器锁(monitor lock)。
当一个线程调用 wait() 方法时,它会释放当前持有的监视器锁,并进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法来唤醒它。
同样,notify() 和 notifyAll() 方法也会释放监视器锁,以便等待的线程可以重新获取锁并继续执行。
因此,这些方法必须在同步代码块中调用,以确保线程能够正确地获取和释放锁。
示例代码
public class Example {
private final Object lock = new Object();
public void doSomething() {
synchronized (lock) {
try {
while (/* condition not met */) {
lock.wait(); // 等待条件满足
}
// 执行相关操作
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public void notifySomething() {
synchronized (lock) {
// 修改条件
lock.notifyAll(); // 通知等待的线程
}
}
}
总结
将 wait() 和 notify() 放在 synchronized 代码块中是为了确保线程安全、遵循监视器规则、避免死锁。
更多大厂面试题,欢迎前往微信搜索小程序 「猿面试」 查看。微信小程序 (猿面试) 包含了 Java、Android、鸿蒙和ArkTS、设计模式、算法和数据结构 相关内容,
Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。
更多面试题:
- 从字节码看 finally 的本质,你能说出这些代码运行结果吗?
- 用final声明的局部变量,能提升性能吗
- 线程池解决什么问题,为什么不推荐使用Executors创建线程池
- 线程同步有那些方式
- 为什么成员变量不需要手动初始化,而局部变量需要手动初始化
- 操作符+号和StringBuilder性能差异
- 一道奇葩的面试题,线程调用2次start方法会怎样
- 鸿蒙,ArkTs 一段诡异的代码
- 揭秘sleep和wait,notify和notifyAll解决什么问题
开源新项目
-
云同步编译工具(SyncKit),本地写代码,远程编译,欢迎前去查看 SyncKit
-
KtKit 小巧而实用,用 Kotlin 语言编写的工具库,欢迎前去查看 KtKit
-
最全、最新的 AndroidX Jetpack 相关组件的实战项目以及相关组件原理分析文章,正在逐渐增加 Jetpack 新成员,仓库持续更新,欢迎前去查看 AndroidX-Jetpack-Practice
-
LeetCode / 剑指 offer,包含多种解题思路、时间复杂度、空间复杂度分析,在线阅读