当前位置: 代码迷 >> 综合 >> 【并发编程】wait、notify()和notifyAll()之间的联系
  详细解决方案

【并发编程】wait、notify()和notifyAll()之间的联系

热度:56   发布时间:2023-12-15 21:18:36.0

目录

  • 锁池与等待池
  • 执行wait()方法
  • 调用notify()/notifyAll()方法
  • notify()可能导致死锁


参考知乎高?回答:java中的notify和notifyAll有什么区别?


锁池与等待池

首先要明白锁池等待池的区别,现在有一个线程A拥有了Obj对象的锁:

锁池:这时候有其他的线程要来竞争这个对象锁,但是线程A在占用这个对象锁,因此其余的线程都在这个Obj对象的锁池中。

等待池:线程A调用了对象Obj的wait()方法,线程A就会释放Obj的对象锁,进入到该对象的等待池中。


执行wait()方法

一个对象调用了wait()方法,则线程会处于该对象的等待池中,等待池中的线程不会去竞争该对象


调用notify()/notifyAll()方法

但是对象调用了notify()/notifyAll方法之后,就会唤醒等待池中的线程,被唤醒的线程会进入到该对象的锁池中。notify()会唤醒一个线程从等待池到锁池,而notifyAll()会唤醒该对象等待池中的所有对象进入到锁池中,准备竞争这个对象锁。

一般来说,高优先级的线程更容易竞争到这个Obj对象锁,一旦竞争到了,就正常执行synchronized方法,执行完毕之后,其余的线程继续竞争Obj。没有竞争成功的线程依旧留在对象的锁池中。

因此,notify()和notifyAll()共同的作用就是将线程从对象的等待池转移到对象的锁池,区别在于前者是唤醒一个线程,后者是唤醒所有等待线程


notify()可能导致死锁

以上的内容也可以用来解释为什么notify()可能会导致死锁,但是notifyAll()并不会:

假如说这个时候Obj的等待池中,已经有线程A, B, C了,此时线程D持有Obj的锁,调用Obj的wait()方法,此时线程D也进入到了等待池中,Obj锁池中的线程得到Obj之后,就再也没有执行过notify()方法,则导致等待池中的线程一直都处于等待状态,永远不会被唤醒进入到该对象的锁池,因此解决的方法就是执行notifyAll(),唤醒所有的等待线程,防止出现死锁情况。

  相关解决方案