原文作者:知乎用户
原文地址:https://www.zhihu.com/question/37601861/answer/145545371
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

今天正好碰到这个问题,也疑惑了好久。看了一圈知乎上的答案,感觉没说到根上。所以自己又好好Google了一下,终于找到了让自己信服的解释。

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

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

Reference:

  • java中的锁池和等待池
  • Java并发编程—线程间协作方式wait()/notify()/notifyAll()原理分析

然后再来说notify和notifyAll的区别

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

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

综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了。上述过程的图示如下:

notify方法和notifyAll()方法两者非常相似,到底该用哪一个,老实说,这个选择有点困难。选择notify的话,因为要唤醒的线程比较少(only one),程序的处理速度当然比notifyAll略胜一筹。但是选择notify时,若这部分处理不好,可能会出现程序挂掉的危险。一般说来,选择notifyAll所写出来的程序代码会比notify可靠。除非你能确定程序员对程序代码的意义和能力限度一清二楚,否则选择notifyAll应该是比较稳扎稳打。

Java并发编程—notify和notifyAll有什么区别?相关推荐

  1. java中的notify和notifyAll有什么区别?

    作者:知乎用户 链接:https://www.zhihu.com/question/37601861/answer/145545371 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业 ...

  2. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  3. Java并发编程—线程间协作方式wait()、notify()、notifyAll()和Condition

    原文作者:Matrix海 子 原文地址:Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 目录 一.wait().notify()和notifyA ...

  4. Java并发编程71道面试题及答案

    Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...

  5. Java并发编程73道面试题及答案——稳了

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户 ...

  6. Java并发编程71道面试题及答案 1

    1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...

  7. Java并发编程75道面试题及答案

    1.在java中守护线程和本地线程区别?java中的线程分为两种:守护线程(Daemon)和用户线程(User).任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bo ...

  8. Java 并发编程73道面试题及答案 ——面试看这篇就够了!

    作者:乌枭 https://blog.csdn.net/qq_34039315/article/details/78549311 1.在java中守护线程和本地线程区别? java中的线程分为两种:守 ...

  9. java并发编程实践 读书笔记_Java - 并发编程实践(读书笔记)

    [注] 同步机制保证:1)原子性 2)内存可见性: Volatile变量只能保证:1)可见性: - 恰当的同步,同步的弱形式,确保对一个变量的更新以可预见的方式告知其他线程. [注] 用锁来协调访问变 ...

最新文章

  1. 19.Mysql索引结构及常见索引的区别
  2. 社区电商才是未来,新科技才是社区电商的核心,社区电商如何实现核心竞争力呢?
  3. iOS之深入解析少见却神奇的NSProxy类的多种使用
  4. 属于服务器操作系统的是,属于服务器操作系统的是
  5. c语言iota怎么用,C++ std::iota用法及代码示例
  6. python中dataframe合并列名日期到季度_python – 如何在特定日期范围内的pandas列DataFrame中对某些值求和...
  7. 百度Q2智能云增长强劲;据悉史上最大 AI 芯片诞生!中兴与奇瑞成立合资公司一起加快开发5G汽车……...
  8. JavaTPoint 移动开发教程【翻译完成】
  9. websocket协议中获取 http 请求字符串
  10. 还原对于服务器失败 备份集中的数据库备份与现有数据库不同
  11. BurpSuite下载CA证书
  12. POJ 2104 划分树
  13. 传智播客-刘意-java深入浅出精华版学习笔记Day07
  14. Redis学习(二):redis集群之cluster模式下的跨节点的批量操作 I
  15. 关于schema文档
  16. 计算机视觉领域的一些牛人博客,研究机构等的网站链接 机器学习算法中文视频教程
  17. FlushMouseMsgBuffer
  18. 学生信息管理系统——用户登录模块问题篇
  19. #编译原理# 概论(一)
  20. 单片机硬件和软件延时是啥意思?

热门文章

  1. 第一周周日DailyReporting——PM(李忠)
  2. step4 . day2标准IO和文件IO 小测试demo
  3. [Splay][线段树] jzoj P5662 尺树寸泓
  4. mock以及特殊场景下对mock数据的处理
  5. 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue
  6. 未解决-hive之drop 表分区失败
  7. JavaScript语言调试技巧
  8. 网页动画结束判断事件
  9. JDBC连接MySQL数据库代码模板
  10. 结构化程序设计03 - 零基础入门学习Delphi12