wait/notify/notifyAll方法需不需要被包含在synchronized块中?这是为什么?

简介: wait/notify/notifyAll方法需不需要被包含在synchronized块中?这是为什么?

wait/notify/notifyAll方法需不需要被包含在synchronized块中

Object.wait(),

Object.notify(),

Object.notifyAll()

都是Object的方法,换句话说,就是每个类里面都有这些方法。

Object.wait():释放当前对象锁,并进入阻塞队列
Object.notify():唤醒当前对象阻塞队列里的任一线程(并不保证唤醒哪一个)
Object.notifyAll():唤醒当前对象阻塞队列里的所有线程

为什么这三个方法要与synchronized一起使用呢?解释这个问题之前,我们先要了解几个知识点

每一个对象都有一个与之对应的监视器
每一个监视器里面都有一个该对象的锁和一个等待队列和一个同步队列

wait()方法的语义有两个,一是释放当前对象锁,另一个是进入阻塞队列,可以看到,这些操作都是与监视器相关的,当然要指定一个监视器才能完成这个操作了

notify()方法也是一样的,用来唤醒一个线程,你要去唤醒,首先你得知道他在哪儿,所以必须先找到该对象,也就是获取该对象的锁,当获取到该对象的锁之后,才能去该对象的对应的等待队列去唤醒一个线程。值得注意的是,只有当执行唤醒工作的线程离开同步块,即释放锁之后,被唤醒线程才能去竞争锁。

notifyAll()方法和notify()一样,只不过是唤醒等待队列中的所有线程

因wait()而导致阻塞的线程是放在阻塞队列中的,因竞争失败导致的阻塞是放在同步队列中的,notify()/notifyAll()实质上是把阻塞队列中的线程放到同步队列中去

值得提的一点是,synchronized是一个非公平的锁,如果竞争激烈的话,可能导致某些线程一直得不到执行。

个人简介

我是一名开发工程师,目前35K,目前做的是无人驾驶,欢迎和大家一起交流开发技术,一起高薪就业,我们还有一起打妖怪的群哦,还有面试题小程序哦!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持“java全栈开发”

相关文章
|
SQL 运维 网络协议
【运维】阿里云宝塔面板部署JavaWeb项目
【运维】阿里云宝塔面板部署JavaWeb项目
1437 0
【运维】阿里云宝塔面板部署JavaWeb项目
|
Dubbo Java 应用服务中间件
Dubbo——对版本号version的理解与使用
Dubbo——对版本号version的理解与使用
1733 0
Dubbo——对版本号version的理解与使用
|
API
Camera2预览方向、拍照方向设置
Camera2预览方向、拍照方向设置
1167 2
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
1789 31
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
设计模式 缓存 前端开发
什么是幂等性?四种接口幂等性方案详解!
本文深入分布式系统中的幂等性问题及其解决方案,涵盖数据库唯一主键、乐观锁、PRG模式和防重Token等方法,关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
什么是幂等性?四种接口幂等性方案详解!
|
缓存 关系型数据库 MySQL
一文彻底弄懂MySQL优化之深度分页
【10月更文挑战第24天】本文深入探讨了 MySQL 深度分页的原理、常见问题及优化策略。首先解释了深度分页的概念及其带来的性能和资源问题。接着介绍了基于偏移量(OFFSET)和限制(LIMIT)以及基于游标的分页方法,并分析了它们的优缺点。最后,提出了多种优化策略,包括合理创建索引、优化查询语句和使用数据缓存,帮助提升分页查询的性能和系统稳定性。
1587 1
|
Ubuntu
kali重新配置系统语言环境“中文”
更新系统:在终端运行 `sudo apt update` 后 `sudo apt upgrade -y`,以升级软件包。语言环境:执行 `sudo dpkg-reconfigure locales`,选择 `zh_CN.UTF-8` 作为语言环境,用箭头键导航,空格键选择,Tab键切换,然后确认。 3. 输入法配置:启动 `fcitx-autostart &`,系统设置中添加汉语拼音输入法。 4. 重启系统:运行 `sudo reboot` 使更改生效。 注意:内容提及的图形界面操作可能适用于基于Debian的系统,如Ubuntu,并且使用了Fcitx作为输入法框架。
393 2
|
缓存 NoSQL Java
接口幂等该如何设计和实现
本文探讨了程序开发中常见的重复操作问题,如多次点击生成多余订单或支付、RPC调用失败后的重试机制滥用及非法重复请求等。通过接口幂等性设计可有效解决这类问题,确保相同请求多次执行结果一致无副作用。文章详细解释了幂等性的概念及其重要性,并提供了具体的设计与实现方法,包括使用唯一标识符、设计幂等操作、事务处理及缓存策略。此外,还讨论了实现幂等性接口所带来的好处,如并发请求处理、失败请求管理及系统集成等,并提出了验证接口幂等性的策略。通过这些技术和方法的应用,可以显著提升系统的稳定性和用户体验。
369 1
|
消息中间件 NoSQL 关系型数据库
一文彻底搞定Redis与MySQL的数据同步
【10月更文挑战第21天】本文介绍了 Redis 与 MySQL 数据同步的原因及实现方式。同步的主要目的是为了优化性能和保持数据一致性。实现方式包括基于数据库触发器、应用层双写和使用消息队列。每种方式都有其优缺点,需根据具体场景选择合适的方法。此外,文章还强调了数据同步时需要注意的数据一致性、性能优化和异常处理等问题。
2823 0
|
存储 缓存 安全
(八)深入并发之Runnable、Callable、FutureTask及CompletableFuture原理分析
关于Runnable、Callable接口大家可能在最开始学习Java多线程编程时,都曾学习过一个概念:在Java中创建多线程的方式有三种:继承Thread类、实现Runnable接口以及实现Callable接口。但是实则不然,真正创建多线程的方式只有一种:继承Thread类,因为只有`new Thread().start()`这种方式才能真正的映射一条OS的内核线程执行,而关于实现Runnable接口以及实现Callable接口创建出的Runnable、Callable对象在我看来只能姑且被称为“多线程任务”,因为无论是Runnable对象还是Callable对象,最终执行都要交由Threa
566 1