Java多线程之wait(),notify(),notifyAll()
在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题。Java语言提供了专门机制以解决这样的冲突,有效避免了同一个数据对象被多个线程同一时候訪问。
wait与notify是java同步机制中重要的组成部分。结合与synchronizedkeyword使用,能够建立非常多优秀的同步模型。
synchronized(this){ }等价于publicsynchronized void method(){.....}
同步分为类级别和对象级别,分别相应着类锁和对象锁。类锁是每一个类仅仅有一个,假设static的方法被synchronizedkeyword修饰,则在这种方法被运行前必须获得类锁;对象锁类同。
首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才可以去调用obj的wait与notify/notifyAll三个方法,否则就会报错:
java.lang.IllegalMonitorStateException:current thread not owner
在调用wait的时候,线程自己主动释放其占有的对象锁,同一时候不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。
所以,notify与notifyAll没有太多的差别,仅仅是notify仅唤醒一个线程并同意它去获得锁,notifyAll是唤醒全部等待这个对象的线程并同意它们去获得对象锁,仅仅要是在synchronied块中的代码,没有对象锁是寸步难行的。事实上唤醒一个线程就是又一次同意这个线程去获得对象锁并向下执行。
notifyAll,尽管是对每一个wait的对象都调用一次notify,可是这个还是有顺序的,每一个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。事实上启动等待对象链中各个线程的也是一个线程,在详细应用的时候,须要注意一下。
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每一个对像都有wait(),notify(),notifyAll()的功能。由于都个对像都有锁,锁是每一个对像的基础,当然操作锁的方法也是最基础了。
wait():
等待对象的同步锁,须要获得该对象的同步锁才干够调用这种方法,否则编译能够通过,但执行时会收到一个异常:IllegalMonitorStateException。
调用随意对象的 wait() 方法导致该线程堵塞,该线程不可继续运行,而且该对象上的锁被释放。
notify():
唤醒在等待该对象同步锁的线程(仅仅唤醒一个,假设有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,并且不是按优先级。
调用随意对象的notify()方法则导致因调用该对象的 wait()方法而堵塞的线程中随机选择的一个解除堵塞(但要等到获得锁后才真正可运行)。
notifyAll():
唤醒全部等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。
通常,多线程之间须要协调工作:假设条件不满足,则等待;当条件满足时,等待该条件的线程将被唤醒。在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中的一个才有机会获得锁继续运行。
谈一下synchronized和wait()、notify()等的关系:
1.有synchronized的地方不一定有wait,notify
2.有wait,notify的地方必有synchronized.这是由于wait和notify不是属于线程类,而是每个对象都具有的方法,并且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。
另外,注意一点:假设要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,由于假设调用完wait,该线程就已经不是currentthread了。
Java多线程之wait(),notify(),notifyAll()的更多相关文章
- java 多线程之wait(),notify,notifyAll(),yield()
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...
- JAVA多线程之wait/notify
本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...
- JAVA多线程之volatile 与 synchronized 的比较
一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...
- java多线程之wait和notify协作,生产者和消费者
这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...
- java多线程之yield,join,wait,sleep的区别
Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...
- Java多线程之ConcurrentSkipListMap深入分析(转)
Java多线程之ConcurrentSkipListMap深入分析 一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...
- Java多线程之Runnable与Thread
Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...
- JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止
JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 背景 当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境 ...
- Java——多线程之Lock锁
Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...
随机推荐
- java 中常见异常
1. Java.lang.NullPointerException 这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的 ...
- UITextView 相关知识点
1.得到UITextView的高度 - (CGRect)contentSizeRectForTextView:(UITextView *)textView { [textView.layoutMana ...
- <转>如何测试大型ERP软件?
大型ERP软件是一个在企业范围内部应用的.高度集成的软件,且操作频繁,数据在各业务系统之间高度共享.那么针对大型ERP软件的特点,我们应该怎么测试呢?要使用怎样的测试方法?需要什么样的测试人员?... ...
- Linux Systemd——在RHEL/CentOS 7中启动/停止/重启服务
RHEL/CentOS 7.0中一个最主要的改变,就是切换到了systemd.它用于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服务进行管理.systemd兼容SysV和Li ...
- 常用的CSS Hack技术集锦
来源:http://www.ido321.com/938.html 一.什么是CSS Hack? 不同的浏览器对CSS的解析结果是不同的,因此会导致相同的CSS输出的页面效果不同,这就需要CSS Ha ...
- 在Ubuntu6.06 在搭建SVN服务器及在windows建立svn+ssh客户端 (续)
接上篇.本篇主要介绍windows下建立svn+ssh客户端. 9.在windows下安装svn客户端,则需安装“TortoiseSVN”.“Puttygen”和“Pageant” 9.1.下载 ...
- <Araxis Merge>Windows平台下的Merge概览
它是什么 Merge是一个来自Araxis的可视化文件比较/合并及文件夹同步的应用程序. 用户界面使用英语.德语.日语.法语.国际西班牙语.汉语(繁体和简体)进行本地化了. 优势 对于软件工程师和网站 ...
- AspNetPager 的使用
下面选用的是新闻发布系统里用的代码. SQL 存储过程: CREATE PROCEDURE procNewsSelectByPager @startRecordIndex int, @endRecor ...
- 基于Node.js的实时推送 juggernaut
基于Node.js的实时推送 juggernaut Juggernaut 基于 Node.js 构建.为浏览器和服务器端提供一个实时的连接,可在客户端和服务器端进行数据的实时推送,适合多角色游戏.聊天 ...
- 【转】Nginx系列(三)--管理进程、多工作进程设计
原博文出于:http://blog.csdn.net/liutengteng130/article/details/46700999 感谢! Nginx由一个master进程和多个worker进程组 ...