为什么wait()、notify()方法需要和synchronized一起使用
提示:更多优秀博文请移步博主的GitHub仓库:GitHub学习笔记、Gitee学习笔记
Obj.wait()与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify必须通过获取的锁对象进行调用**,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){…}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。
1. 不一起使用导致的后果
public class Haha {
public Map<String,String> map=new HashMap<>();
public void haha() throws InterruptedException {
synchronized (map){//使用map加锁
System.out.println("haha method is run");
this.wait();//用当前对象,调用wait方法会报错;正确的写法是map.wait()
}
}
}
public class Test {
public static void main(String[] args) {
new Thread(()->{
try {
new Haha().haha();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
在上述代码中由于Haha类的haha方法中使用map加的锁,但又试图使用this.wait方法释放锁此时会报错:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PMmhumDw-1585273461081)(…/images/7.png)]
2. 为什么要在一起使用
Object.wait(),Object.notify(),Object.notifyAll()都是Object的方法,换句话说,就是每个类里面都有这些方法。
- Object.wait():释放当前对象锁,并进入阻塞队列
- Object.notify():唤醒当前对象阻塞队列里的任一线程(并不保证唤醒哪一个)
- Object.notifyAll():唤醒当前对象阻塞队列里的所有线程
为什么这三个方法要与synchronized一起使用呢?解释这个问题之前,我们先要了解几个知识点
- 每一个对象都有一个与之对应的监视器
- 每一个监视器里面都有一个该对象的锁以及一个等待队列和一个同步队列
wait()方法的语义有两个,一是释放当前对象锁,另一个是进入阻塞队列,可以看到,这些操作都是与监视器相关的,当然要指定一个监视器才能完成这个操作了
notify()方法也是一样的,用来唤醒一个线程,你要去唤醒,首先你得知道他在哪儿,所以必须先找到该对象,也就是获取该对象的锁,当获取到该对象的锁之后,才能去该对象的对应的等待队列去唤醒一个线程。值得注意的是,只有当执行唤醒工作的线程离开同步块,即释放锁之后,被唤醒线程才能去竞争锁。
因wait()而导致阻塞的线程是放在阻塞队列中的,因竞争失败导致的阻塞是放在同步队列中的,notify()/notifyAll()实质上是把阻塞队列中的线程放到同步队列中去
为了便于理解,你可以把线程想象成一个个列车,对象想象成车站,每一个车站每一次能跑一班车,这样理解起来就比较容易了。
值得提的一点是,synchronized是一个非公平的锁,如果竞争激烈的话,可能导致某些线程一直得不到执行。
参考文章:https://blog.csdn.net/qq_39907763/article/details/79301813
为什么wait()、notify()方法需要和synchronized一起使用的更多相关文章
- java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader
1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...
- java多线程详解(6)-线程间的通信wait及notify方法
Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...
- Java 多线程(七) 线程间的通信——wait及notify方法
线程间的相互作用 线程间的相互作用:线程之间需要一些协调通信,来共同完成一件任务. Object类中相关的方法有两个notify方法和三个wait方法: http://docs.oracle.com/ ...
- Java使用wait() notify()方法操作共享资源
Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写. 2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线 ...
- 并发编程之 wait notify 方法剖析
前言 2018 元旦快乐. 摘要: notify wait 如何使用? 为什么必须在同步块中? 使用 notify wait 实现一个简单的生产者消费者模型 底层实现原理 1. notify wait ...
- Java中wait()和notify()方法的使用
1. wait方法和notify方法 这两个方法,包括notifyAll方法,都是Object类中的方法.在Java API中,wait方法的定义如下: public final void wait( ...
- Java使用wait() notify()方法操作共享资源详解_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方 ...
- wait/notify方法
执行wait方法会释放锁,执行notify不会释放锁 package com.qf.test05.pojo; /** * @author qf * @create 2018-09-18 10:41 * ...
- 从Guarded Block来看Java中的wait和notify方法
目录 预备知识 概览 线程同步 wait()方法 wait() wait(long timeout) wait(long timeout, int nanos) notify() & noti ...
- 为什么Java中 wait 方法需要在 synchronized 的方法中调用?
另一个棘手的核心 Java 问题,wait 和 notify.它们是在有 synchronized 标记的方法或 synchronized 块中调用的,因为 wait 和 modify 需要监视对其上 ...
随机推荐
- centos环境tomcat配置SSL
环境: centos7.9 tomcat9 jdk1.8 一.阿里云申请 免费SSL 按照官网的方法并未成功启动! 443 80端口加入安全组 阿里云申请免费ssl 下载后解压将localhost-r ...
- MogDB/openGauss学习笔记-获取对象DDL
MogDB/openGauss 学习笔记-获取对象 DDL 本文出处:https://www.modb.pro/db/399230 内置函数 omm2=# \df *def List of funct ...
- 简单3步,OpenHarmony上跑起ArkUI分布式小游戏
转自:OpenAtom OpenHarmony 在9月30日更新的 OpenHarmony3.0 LTS 上,标准系统新增支持了方舟开发框架(ArkUI).分布式组网和 FA 跨设备迁移能力等新特性, ...
- CentOS防火墙操作命令
CentOS防火墙操作命令 1.查看防火墙服务状态 systemctl status firewalld.service 或者查看防火墙的状态: 1 firewall-cmd --state 2.开启 ...
- leetcode:1380. 矩阵中的幸运数
1380. 矩阵中的幸运数 给你一个 m * n 的矩阵,矩阵中的数字 各不相同 .请你按 任意 顺序返回矩阵中的所有幸运数. 幸运数是指矩阵中满足同时下列两个条件的元素: 在同一行的所有元素中最小 ...
- 图像验证码识别,字母数字汉子均可cnn+lstm+ctc
图形验证码如下: 训练两轮时的准确率:上边显示的是未识别的 config_demo.yaml System: GpuMemoryFraction: 0.7 TrainSetPath: 'train/ ...
- 力扣306(java)-累加数(中等)
题目: 累加数 是一个字符串,组成它的数字可以形成累加序列. 一个有效的 累加序列 必须 至少 包含 3 个数.除了最开始的两个数以外,序列中的每个后续数字必须是它之前两个数字之和. 给你一个只包含数 ...
- Java 应用压测性能问题定位经验分享
简介: 问题千千万,但只要修练了足够深厚的内功,形成一套属于自己的排查问题思路和打法,再加上一套支撑问题排查的工具,凭借已有的经验还有偶发到来的那一丝丝灵感,相信所有的问题都会迎刃而解. 作者:凡勇 ...
- 阿里云RemoteShuffleService 新功能:AQE 和流控
简介:阿里云EMR 自2020年推出 Remote Shuffle Service(RSS)以来,帮助了诸多客户解决 Spark 作业的性能.稳定性问题,并使得存算分离架构得以实施.为了更方便大家使 ...
- [ML] 科学编程语言 Octave 简单操作
octave 是和 matlab 类似的软件,可以方便的进行矩阵计算.图形绘图. matlab 收费,octave 是 gnu 开源软件. Mac 安装: $ brew install octave ...