先说两个概念:锁池和等待池

  • 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
  • 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中

Reference:java中的锁池和等待池

链接:https://www.zhihu.com/question/37601861/answer/145545371

然后再来说notify和notifyAll的区别

  • 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁
  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争
  • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

Reference:线程间协作:wait、notify、notifyAll

综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。

有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了

最新文章

  1. IOS关于LKDBHelper实体对象映射插件运用
  2. jQuery插件中文乱码解决办法
  3. VBA_Excel_教程:字典类型
  4. oracle 性能优化建议小结
  5. PHP 按二维数组的键值排序
  6. Asp.Net生命周期系列二
  7. 继承在WCF中的问题和解决办法
  8. 黑客是怎样绕过WAF之三重防护绕过讲解
  9. bootstrap -- 一个标签中,同时有 col-xs , col-sm , col-md , col-lg
  10. [D3] 6. Color Scale
  11. RecycleView 瀑布流滑动移位
  12. python os模块文件相关
  13. CodeFirst 表之间的关联
  14. JS高级. 05 词法作用域、变量名提升、作用域链、闭包
  15. 批量修改git仓库地址脚本
  16. 第25章 退出外部身份提供商 - Identity Server 4 中文文档(v1.0.0)
  17. PAT 1086 就不告诉你(15 )(代码)
  18. JVM 目录
  19. win10 标注工具LabelImg 安装使用
  20. [C/C++] C++ Primer学习笔记

热门文章

  1. Vxworks驱动程序的结构
  2. 用VSCode开发一个asp.net core 2.0+angular 5项目(4): Angular5全局错误处理
  3. H5 EventSource 实现web页面推送功能demo
  4. CDQ分治嵌套模板:多维偏序问题
  5. [CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)
  6. 版本控制-Git对象
  7. Spring AOP梳理
  8. 2018java平均工资,想转行学java的快点上车
  9. C#多线程之异步编程
  10. c# MongoDB Driver 官方教程翻译