wait/notify

[size=large][color=red]转帖自http://md20040208.blog.163.com/blog/static/3006942720092319926566/[/color][/size]

在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。例如:

synchronized(obj) {
while(!condition) {
obj.wait();
}
obj.doSomething();
}

当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait() , 放弃对象锁.

之后在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:

synchronized(obj) {
condition = true;
obj.notify();
}

需要注意的概念是:

# 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。

# 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A。

# 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。

# 如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。

# obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。

# 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出 synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

wait() 是使持有对象锁的线程释放锁;
wait(long)是使持有对象锁的线程释放锁时间为long(毫秒)后,再次获得锁,wait()和wait(0)等价;
notify() 是唤醒一个正在等待该对象锁的线程,如果等待的线程不止一个,那么被唤醒的线程由jvm确定;
notifyAll 是唤醒所有正在等待该对象锁的线程.

并且应该优先使用notifyAll()方法,因为唤醒所有线程比唤醒一个线程更容易让jvm找到最适合被唤醒的线程.

对于上述方法,只有在当前线程中才能使用,否则报运行时错误java.lang.IllegalMonitorStateException: current thread not owner.
从实现角度来分析:
在线程调用wait()方法时,需要把它放到一个同步段里,即应该在调用前使用
1java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客synchroed(this)java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客{
2java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客 thread.wait();
3java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客 java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客
4java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客}
5java多线程设计wait/notify机制 (synchronized与对象锁) - ruby - ruby的博客


否则将会出现"java.lang.IllegalMonitorStateException: current thread not owner"的异常。



synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。

wait()/notify():调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

synchronized和wait()、notify()的关系:

1.有synchronized的地方不一定有wait,notify

2.有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。

另外,请注意一点:如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是current thread了。

注:调用wait()方法前的判断最好用while,而不用if;while可以实现被wakeup后thread再次作条件判断;而if则只能判断一次;

线程的四种状态

  1. 新状态:线程已被创建但尚未执行(start() 尚未被调用)。

  2. 可执行状态:线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它执行。

  3. 死亡状态:正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果,但是不被推荐,前者会产生异常,后者是强制终止,不会释放锁。

  4. 阻塞状态:线程不会被分配 CPU 时间,无法执行。


首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对 (wait()/notify()) 却直接隶属于 Object 类,也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。

  而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

  其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在synchronized 方法或块中当前线程才占有锁,才有锁可以释放。

  同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现 llegalMonitorStateException 异常。

  wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语(这一对方法均声明为synchronized)。

它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。关于

wait() 和 notify() 方法最后再说明两点:

  第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。

  第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。

  谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。

  以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify()方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用中我们应该灵活使用各种方法,以便更好地达到我们的目的。
如何利用CANoe在两路CAN通道之间创建网关(gateway) CANoe网关,利用CAPL实现CAN转发 阅读详情

相关推荐

博客系统 - 系统简介与首页设计

用Bootstrap实现手机端的博客导航栏效果。

m0_53450409的博客 1238

wait和notify方法详解

wait() 使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,这个方法的行为就像它只是执行wait(0)一样(如果没有当前对象notify()唤醒就会一直等待)。 1.当前线程必须拥有此对象的monitor监视器(锁)。2.当前线程调用wait()方法,线程就会释放此锁的所有权,并等待,3.直到另一个线程通过调用notify方法或notifyAll方法通知在该对象的监视器(锁)上等待的线程唤醒。4.然后线程等待,直到它可以重新获得监视器(锁)的所有权然

qq_42261668的博客 3039

别再混淆了!一张图看懂SAP特殊采购类30/40/70/80的区别与选型指南

本文深度解析SAP特殊采购类30/40/70/80的核心逻辑与业务影响,通过对比框架和真实案例帮助用户掌握其适用边界。重点介绍委外加工(类型30)、工厂间转移(类型40/70)及计划与执行分离(类型80)的配置要点与常见问题,提供选型决策树和实施检查清单,助力企业优化供应链管理。

weixin_26938645的博客 454

wait()、notify()、notifyAll()方法

弄清楚调用下列方法后线程状态的变化 wait()方法 1、wait()方法是Object类的方法 2、wait()方法的作用是使当前执行代码的线程进行等待,直到被唤醒 3、调用wait()方法,没有持有适当的锁会抛出异常,所以调用wait()方法前要拥有锁 4、wait()方法执行后,当前线程释放锁 sychronized (object){ object.wait(); } (1)释放object中的锁,notify()方法调用也需要持有锁,不释放的话,该线程就没法被唤醒了 (2)把线程放在o.

qq_44743329的博客 188

YOLO26 多任务统一架构:检测 / 分割 / 姿态 / OBB 设计

YOLO26提出了一种多任务统一架构,整合了目标检测、实例分割、姿态估计和旋转框检测(OBB)四大计算机视觉任务。该架构采用共享Backbone和Neck的设计,配合轻量级任务特定Head,解决了传统方法中多模型并行带来的高开发成本、大内存占用和低推理效率问题。核心设计包括:1)共享特征提取层实现参数复用;2)模块化Head结构支持灵活任务组合;3)统一接口实现单模型多任务处理。实验表明,该架构在保持各任务性能的同时显著提升了系统效率,为多任务视觉系统提供了新的实现范式。

一键难忘的博客 705

YOLOv12改进策略【卷积层】| CVPR-2020 利用DynamicConv 动态卷积 结合A2C2f进行二次创新,提高精度

在大规模视觉预训练中,通常模型的性能受到数据、参数和FLOP三个关键因素的影响。一般来说,模型的参数数量越多,FLOP也越高,但在移动设备等对计算资源有限制的场景下,需要低FLOP的模型同时又希望模型能从大规模预训练中受益。传统的方法很难在增加参数的同时保持低FLOP,因此需要一种新的设计来解决这个问题,模块应运而生。

Limiiiing的博客 828

wait/notify使用详解

永远在synchronized方法或对象里使用wait/notify(All),不然JVM报java.lang.IllegalMonitorStateException。可以在任何地方调用线程对象的sleep方法,wait方法只能在同步代码块或同步方法中调用;永远在线程间共享对象(生产者消费者中为缓冲区队列)上使用wait/notify(All)调用线程对象的sleep方法后,不释放锁,调用对象的wait方法,释放对象获得的锁。sleep是Thread中定义的方法, wait是Object中定义的方法;

算法小生 702

TC397 EB MCAL开发从0开始系列 之 [17.1] ETH配置实战 - ping/发送

TC397 MCAL 从0开始之 ETH ping测试

yy九歌的博客 1507

wait和notify方法

wait和notify相关概念: wait和notify方法是Java同步机制中重要的组成部分, 他们只有在Synchronized方法或Synchronized代码块中才能使用 否者就会报java.lang.IllegalMonitorStateExceprion异常 当Synchronized方法或者Synchronized代码块中的wait() 方法被调用时,当前线程将被

Terrence_he的博客 551

华为OD机试真题 新系统 2026-04-22 Python&JS 实现【小学生班长选举增强版】

9 月份开学第一天,小学某班级进行班长选举活动,班级共有 N 个学生,每个学生最多可投 3 票(对同一个人只能投一票),也可以弃权不投票,大家投票时写上对应学生的名字。 假设学生不存在重名。考虑到部分少数民族名字带分隔,且整体较长,同学在投票时为了方便,允许同学写全称,也可以只写其中的部分连续段。 例如班级里只有 2 个少数民族名称带点的同学:

MISAYAONE的博客 317

C# WPF上位机开发(利用tcp/ip网络访问plc)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 c# wpf如果是用来开发非标上位机的,那么和plc的通信肯定是少不了的。而且,大部分plc都支持modbus协议,所以这个时候如果有一个库可以帮助我们和plc设备进行modbus通信,那就非常方便的。目前NuGet下关于modbus的函数库还是有一些的,比如EasyModbus。

嵌入式-老费,一个分享专业嵌入式知识的blog 2530

wait和notify的用法

package _7wait和notify; // wait() // notify() // notifyAll(); // 通过调用某对象的wait()方法能让当前线程阻塞 // 通过调用某对象的notify()方法能唤醒一个正在等待该对象的线程 // 通过调用某对象的notifyAll()能唤醒所有正在等待该对象的线程 public class TestDemo {     pub...

苏凯的博客 2685

Python航空航天设计神器!从入门到实操,小白也能搞定飞机优化

AeroSandbox的核心价值的是:​降低航空工程优化的门槛,用Python实现高效、简洁的工程设计​。无论是科研、学习还是实际项目,它都能帮你节省大量时间,不用再手动推导导数、编写复杂的优化逻辑。对于新手来说,建议先从案例1(Rosenbrock函数)入手,熟悉优化流程,再尝试案例2(翼型优化),逐步掌握核心用法;对于有航空相关需求的小伙伴,可以深入研究内置的物理模型,结合自己的项目进行定制化开发。最后,互动时间到!👉 你是用AeroSandbox做科研、练手还是实际项目?

源代码杀手的博客 124

Java等待唤醒机制wait/notify深入解析

本文将帮助你彻底弄明白Java的wait/notify等待唤醒机制。为了弄明白wait/notify机制,我们需要清楚线程通信、volatile和synchronized关键字、wait/notify方法、Object的monitor机制。本文将会从这几个方面详细讲解Java的wait/notify等待唤醒机制。 一、线程通信 如果一个线程从头到尾执行完也不和别的线程打交道的话,那就不会有各种安全性问题了。但是协作越来越成为社会发展的大势,一个大任务拆成若干个小任务之后...

1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

wait/notify机制

wait/notify(等待/通知)机制在生活中比比皆是,比如在就餐时就会出现,如图:厨师和服务员要在"菜品传递台"上交互,在这期间会想到几个问题:1)厨师做完一个菜的时间未知,所以厨师将菜品放到"菜品传递台" 上的时间也未知。2)服务员取到菜的时间取决于厨师,所以服务员就有"wait"状态。3)服务员如何能取到菜呢?这又得取决于厨师。厨师将菜放在“菜品传递台”上,其实就是相当于一种notify,这时服务员才可以拿到菜并交给就餐者。4)在这个过程中出现了“wait/notify机制”。

m0_62943934的博客 762

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C++ wait/notify机制

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33950035的博客 1万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

python wait notify_C++ wait/notify机制

1,考虑如下Reader/Writer情景:有一个共享FIFO,写线程往FIFO里面写数据,读线程从FIFO里面读取数据。站在读者的角度,如果FIFO为空,读者有两种选择:一种是轮询FIFO,直到FIFO不空,读取数据。这种轮询的方式会占满CPU,浪费计算资源;另外一种是读者wait在某个等待队列上,主动放弃CPU资源,等待写者写入FIFO后,再唤醒等待在这个队列上的读者。这就是wait/noti...

weixin_39775910的博客 170

关于wait/notify以及顺序打印

1.等待和唤醒是同一个对象 2.notify只会唤醒一个线程 使用角度 1.Object.wait() 会抛出 InterruptedException 2.调用object.wait() 必须首先对object(monitor lock) 进行加锁 class Main{ private static Object object = new Object(); private ...

question_mark的博客 719

4、wait/notify的原理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言小故事wait/notify的原理API介绍Sleep(long n)和wait(long n)的区别:Wait notify的正确使用姿势 前言 上一章https://blog.youkuaiyun.com/m0_45364328/article/details/124925295 我们介绍了synchronized的原理,并提出了Monitor的概念,这张我们介绍一下wait/notify的原理,加深对Monitor的理解 小故事 .

m0_45364328的博客 405

wait/notify/join

线程通信 1,共享内存 2,wait/notify -> 基于某一个条件来等待或者唤醒 ,从而进行通信 可以基于wait()方法构建生产者消费者模型 以上图示说明:1,两个线程必须抢占同一把锁 2,wait/notify 方法必须在synchronized方法里面 wait()方法阻塞 一定会释放锁 注意此处释放锁但是不一定代表同步代码块执行结束 notify() 不会释放锁 //以下代码通过Queue这一个共享数据结构 来进行生产者消费者通信 基于某一个...

u012693823的博客 292

Java synchronized中的wait/notify机制详解

Java synchronized中的wait/notify机制是基于对象监视器锁实现的线程通信方式。wait()会释放锁并使线程进入等待状态,notify()随机唤醒一个等待线程,notifyAll()唤醒所有线程。使用时必须在同步块内调用,并通过循环检查条件来避免虚假唤醒。该机制适用于生产者-消费者等模式,但要注意IllegalMonitorStateException和丢失唤醒等问题。相比Java 5的Condition接口,wait/notify更简单但不支持多条件。正确使用这一机制是编写可靠并发程

weixin_47242663的博客 1140

wait / notify、单例模式

本文主要介绍了Java多线程中的wait/notify机制和单例模式。在wait/notify部分,详细讲解了wait方法的使用条件、与sleep的区别、notify的唤醒机制以及线程饥饿问题,强调wait必须配合synchronized使用并会释放锁。在单例模式部分,对比了饿汉模式(类加载时创建实例)和懒汉模式(首次使用时创建实例)的实现方式,重点分析了懒汉模式在多线程环境下的线程安全问题及解决方案,包括双重检查锁定、volatile关键字的使用等。

z141042的博客 895

详细解析wait/notify

关于wait和notify

m0_62609939的博客 1359

为什么wait/notify必须要强制要求放在synchronized中

为什么wait/notify必须要强制要求放在synchronized中为什么wait/notify必须要强制要求放在synchronized中如果Object.wait()/notify不需要同步为什么要在JVM层面抛异常如果没有wait/notify 为什么wait/notify必须要强制要求放在synchronized中 在日常开发,我们都知道wait/notify有着非常固定的一套模板,就是下面的样子,synchronized同步块包裹着Object.wait()方法,如果不通过同步块包住的话JVM

huanglong0438的专栏 3149

Java并发编程之Wait/Notify

通过wait()notify()wait():释放锁并等待条件满足。notify():通知等待线程条件已变化。正确使用这两个方法需严格遵循同步规则和条件检查,避免线程饥饿或死锁问题。拓展:wait与sleep1. 所属类与调用方式方法所属类调用方式wait()Object必须在同步块中调用(需持有对象锁)sleep()Thread静态方法,可直接调用(无需持有锁)2. 锁的释放行为方法是否释放锁?锁释放时机wait()✅释放锁调用wait()后立即释放锁,线程进入等待状态。

helloworldcnm的博客 889
上一篇: 集群监控软件Ganglia在Ubuntu Server上的部署
下一篇: linux文件权限总结
conservatism
博客等级 码龄19年 0粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值