java 中的锁池(monitor)和等待池(waitset)

/ Java / 没有评论 / 1765浏览

java 中的锁池(monitor)和等待池(waitset)

程序就是模仿世界!比如队列就是模仿人们的排队场景,再比如工厂模式,代理模式等都是和现实生活息息相关的场景衍生而来。在前面还记得我们的 synchronized 锁吗?还记得 Object 的 wait 方法吗?它们分别有各自的池,及:锁池和等待池。本文结合前面的内容来说说 java 中的锁池和等待池。

wait()方法

wait() 使当前线程处于等待状态,直到另外的线程调用 notify 或 notifyAll 将它唤醒。但是在等待唤醒的期间,它处在等待唤醒的池子中,也就是我们所说的等待池中。当调用 wait() 方法后,会释放锁,进入等待池。当调用 notify() 或 notifyAll() 后唤醒该对象监听的其中一个或所有线程(规则取决于JVM厂商,FILO,FIFO,随机…)。

等待池

假设线程 xttblog 调用了某个对象的 wait() 方法,则 xttblog 线程就会释放该对象的锁(因为 wait() 方法必须出现在 synchronized 中,所以在执行 wait() 方法之前 xttblog 线程就已经拥有了该对象的锁),同时线程 xttblog 进入到了该对象的等待池中。如果有其它线程调用了相同对象的 notifyAll() 方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,从新争夺锁的拥有权。如果另外的一个线程调用了相同对象的 notify() 方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池。

wait() 对应等待池,synchronized 对应锁池。

加了 synchronized 关键字的地方就会有相应的获取锁的步骤。未竞争到锁的线程会加入到锁池。

锁池

假设线程 xttblog 已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用该对象的 synchronized 方法(或者 synchronized 块),其他未获得锁的线程在进入对象的 synchronized 方法之前都需要先获得该对象的锁的拥有权,但是该对象的锁目前正被 xttblog 线程拥有,所以这些线程就进入了该对象的锁池中。

等待池和锁池中的资源只要重新获得了对象的拥有权,那么就会被对应的池剔除。