锁池、等待池、notify详解
线程状态图示

锁池和等待池
java中,每个对象都有两个池,锁池和等待池。
锁池:某个线程已经拥有了某个对象的锁,其他想要获取该对象的锁的线程就会进入该对象的锁池中;
⭕举例解释:
假设线程A已经拥有了某个对象的锁(这里是对象 不是类),其他线程想要调用这个对象的某个synchronized方法或者块,因为这些线程在进入对象的synchronized方法之前必须先获取该对象锁的拥有权,但此时该对象的锁正被线程A所拥有,所以这些线程就进入了该对象的锁池中。
等待池:已经拥有某个对象的锁的线程调用了wait()方法,该线程将进入该对象的等待池去,等待池中的线程不竞争该对象的锁。
⭕举例解释:
假设线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,所以在执行wait()方法前线程A就拥有了该对象的锁),之后线程A就进入到了该对象的等待池中。
如果其他一个线程调用了相同对象的notify()方法,那么会随机取出一个该对象等待池中的线程进入到该对象的锁池中;如果调用了相同对象的notifyAll()方法,那么处于该对象等待池中的所有线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。
当执行该对象的notify()方法时,随机将等待池中的一个线程移到锁池中;当执行该对象的notifyAll()方法时,将等待池中的所有线程移到锁池中。
锁池中的线程可以竞争该对象的锁。
图示锁池和等待池


为什么wait、notify、notifyAll方法必须在synchronized中调用?
上述内容中我们知道,必须在synchronized方法中使用wait()方法、notify()及notifyAll()方法。为什么?
wait 和 nodify 需要监视对其调用的 Object。
JVM 在运行时会强制检查 wait 和 notify 有没有在 synchronized 代码中,如果没有的话就会报非法监视器状态异常(IllegalMonitorStateException),但这也仅仅是运行时的程序表象,那为什么 Java 要这样设计呢?其实这样设计的原因就是为了防止多线程并发运行时,程序的执行混乱问题。
⭕举例解释:
实现一个自定义阻塞队列。 这里的阻塞队列是指读操作阻塞,也就是当读取数据时,如果有数据就返回数据,如果没有数据则阻塞等待数据。
如果 wait 和 notify 不强制要求加锁,那么在线程 1 执行完判断之后,尚未执行休眠之前,此时另一个线程添加数据到队列中。然而这时线程 1 已经执行过判断了,所以就会直接进入休眠状态,从而导致队列中的那条数据永久性不能被读取,这就是程序并发运行时“执行结果混乱”的问题。
此处引用稀土掘金作者(Java中文社群)文章,链接:https://juejin.cn/post/7067322092936495112。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)