区别

  • notify:只会唤醒等待该锁的其中一个线程。
  • notifyAll:唤醒等待该锁的所有线程。

既然notify会唤醒一个线程,并获取锁,notifyAll会唤醒所有线程并根据算法选取其中一个线程获取锁,那最终结果不都是只有一个线程获取锁吗?那JDK为什么还需要做出来这两个方法呢?这两种同步方法本质上会有什么区别?

这还要从对象内部锁的调度说起。

对象内部锁

其实,每个对象都拥有两个池,分别为锁池(EntrySet)和(WaitSet)等待池。

  • 锁池:假如已经有线程A获取到了锁,这时候又有线程B需要获取这把锁(比如需要调用synchronized修饰的方法或者需要执行synchronized修饰的代码块),由于该锁已经被占用,所以线程B只能等待这把锁,这时候线程B将会进入这把锁的锁池。
  • 等待池:假设线程A获取到锁之后,由于一些条件的不满足(例如生产者消费者模式中生产者获取到锁,然后判断队列为满),此时需要调用对象锁的wait方法,那么线程A将放弃这把锁,并进入这把锁的等待池。

如果有其他线程调用了锁的notify方法,则会根据一定的算法从等待池中选取一个线程,将此线程放入锁池。
如果有其他线程调用了锁的notifyAll方法,则会将等待池中所有线程全部放入锁池,并争抢锁。

锁池与等待池的区别:等待池中的线程不能获取锁,而是需要被唤醒进入锁池,才有获取到锁的机会。

问题复现

那么使用notify和notifyAll到底会有什么区别呢?
请看下面一组生产者消费者的例子。
有两个生产者t1和t2,两个消费者t3和t4,以及一个长度为1的队列。

  1. 初始状态,这四个线程全部进入锁池,等待抢占锁。
  2. t3获取到锁,但是队列为空,故t3进入等待池。
  3. t4获取到锁,但是队列为空,故t4进入等待池。
  4. t1获取到锁,生产,队列满,调用notify,唤醒一个线程。由于此时t3和t4都在等待池中,所以会有一个线程从等待池进入锁池,假设此处t3进入锁池。
  5. 此时,锁池有t2和t3两个线程,假设t2获取到了锁,但是队列满,故t2进入等待池,放弃锁。
  6. 此时,t3获取到锁,消费,notify,由于此时等待池有两个线程t2和t4,假如唤醒的是t2,没问题开始生产,但是若唤醒的是t4,则因队列为空,继续wait。
  7. 此时若t1和t3已经执行结束,t1不在生产,t3不再消费,则t2和t4会一直留在锁池,行程死锁。

如果此处使用notifyAll,则会把等待池中所有线程唤醒,不会形成所有线程都位于等待池,无法唤醒的情况,也就不会形成死锁,当然了,使用notifyAll方法会更加低效一些。

如果此处是一个生产者一个消费者的情况,使用notify没有任何问题,且效率更高。

Object的notify和notifyAll方法的区别相关推荐

  1. Object类九大方法之notify和notifyAll方法

    Object类九大方法之notify和notifyAll方法 notify()方法表示,当前的线程已经放弃对资源的占有, 通知等待的线程来获得对资源的占有权,但是只有一个线程能够从wait状态中恢复, ...

  2. 【面试题】notify() 和 notifyAll()方法的使用和区别

    [面试题]notify() 和 notifyAll()方法的使用和区别 Java中notify和notifyAll的区别 何时在Java中使用notify和notifyAll? [问]为什么wait( ...

  3. 为什么wait、notify、notifyAll方法定义在Object中而不是Thread类中

    多线程概述 Java是一个支持多线程的开发语言,多线程并发执行任务可以充分利用CPU资源,提高多任务并发执行效率(注意区分:多线程并不会加快任务的执行速度,而是可以充分利用多核CPU让线程轮流进行工作 ...

  4. 用实例揭示notify()和notifyAll()的本质区别

    用实例揭示notify()和notifyAll()的本质区别 收藏 notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法.两者的最大区别在于: notifyA ...

  5. notify()和notifyAll()的本质区别

    notify()和notifyAll()的本质区别 notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法.两者的最大区别在于: notifyAll使所有原来在 ...

  6. notify() 和 notifyAll() 有什么区别?

    notify() 和 notifyAll() 有什么区别? 先解释两个概念. 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池,等待池中的线程 ...

  7. notify()和 notifyAll()有什么区别?

    在Java中,notify()和notifyAll()都可以用于线程的唤醒,但它们有以下几个区别: 1. 唤醒数量不同 notify()方法只会随机唤醒等待队列中的一个线程,而notifyAll()方 ...

  8. 第五章 Java 中的 wait、notify 和 notifyAll 方法示例

    您可能已经注意到 Object 类具有三个 final 方法,分别称为 wait.notify 和 notifyAll.这些方法用于线程间通信.Java 5 引入了执行器框架,它为您处理线程间通信,并 ...

  9. notify() 和 notifyAll()方法的使用和区别

    一.区别 notify()和notifyAll()都是用来用来唤醒调用wait()方法进入等待锁资源队列的线程,区别在于: notify() 唤醒正在等待此对象监视器的单个线程. 如果有多个线程在等待 ...

最新文章

  1. sublime text使用小技巧
  2. 36.rustc编译参数.txt
  3. C语言高级技术之--游戏属性修改器(背景故事)
  4. python开发stm32软件_ADB+Python+STM32 实现 微信跳一跳辅助
  5. Vue3.0 + Ts 项目使用element-plus 自动按需导入 使用v-loading报错
  6. oracle改成归档模式_将Oracle数据库改为归档模式并启用Rman备份
  7. FDM3D打印技术原理简析
  8. html动画如何延迟,css3animation延迟
  9. java 调用 yed 绘制 流程图_流程图绘制软件──yEd
  10. Windows系统主机加固
  11. Ceph Calamari监控配置
  12. mysql产品分类_MySQL习题1 一对多实例 产品和分类
  13. oracle vm virtualbox 64位,virtualbox
  14. 四川大学网络教育计算机应用基础,四川大学网络教育学院《计算机应用基础》第一次作业...
  15. ps保存图片时为了可以发送到微信中(微信大于25M的图片不能发送) 应该这样保存图片!!!...
  16. 手把手教你写shell脚本——shell循环结构
  17. 代购商城app的开发优势
  18. Android开发-基于ijkplayer框架开发网络电视直播播放器的实现
  19. 微博mysql表设计思路
  20. windows共享文件夹报错:登录失败: 禁用当前的账户 解决办法

热门文章

  1. MATALB-结构体
  2. 【Python入门】Python的Dict容器一
  3. Python读取文本文件的几种方式
  4. 模型训练技巧:warmup学习率策略
  5. timedatectl的详细用法
  6. 网络安全风险与防范方法
  7. 第十六章 综合实例——《跟我学Shiro》
  8. 软件测试技术(五)软件测试流程
  9. 中基鸿业低收入家庭如何理财
  10. 单线激光雷达SLAM(二)特征识别——断点、角点