在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题。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()的更多相关文章

  1. java 多线程之wait(),notify,notifyAll(),yield()

    wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...

  2. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

  3. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

  4. java多线程之wait和notify协作,生产者和消费者

    这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...

  5. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  6. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

  7. Java多线程之Runnable与Thread

    Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...

  8. JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止

    JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 背景 当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境 ...

  9. Java——多线程之Lock锁

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

随机推荐

  1. [Tommas] 一种有效的测试策略(转)

    在最近的一个大型项目中,我们在早期就定下了一个目标:不会在软件中使用大量QA人员专注于手工测试.通过手工测试发现bug极其耗时且成本高昂,这促使团队尝试尽可能的将质量内嵌到产品内部.但这并不意味着手工 ...

  2. Ubuntu14.04下Python3.4启动IDLE

    1.在Ubuntu14.04 LTS版本中,已经自行安装了python,可以在Terminal(CTRL+ALT+T)中输入:ls /usr/bin | grep python 进行查看. 如果想运行 ...

  3. Oracle11g TNS-12541:TNS无监听程序

    Oracle11g TNS-12541:TNS 无监听程序 问题描述:Oracle11.2客户端访问服务器端服务一直正常,隔了一段时间没有用,再次连接时出现错误“TNS-12541:TNS 无监听程序 ...

  4. 内核源码分析之软中断(基于3.16-rc4)

    1.和软中断相关的数据结构: softing_vec数组(kernel/softirq.c) static struct softirq_action softirq_vec[NR_SOFTIRQS] ...

  5. Getting Started(Google Cloud Storage Client Library)

    在运行下面的步骤之前,请确保: 1.你的项目已经激活了Google Cloud Storage和App Engine,包括已经创建了至少一个Cloud Storage bucket. 2.你已经下载了 ...

  6. ffmpeg内置aac编码器正式发布

    https://www.ffmpeg.org/#aac_encoder_stable February 15th, 2016, FFmpeg 3.0 "Einstein" FFmp ...

  7. No module named BeautifulSoup

    遇到 No module named BeautifulSoup 错误,但是的确从官方下载了BeautifulSoup,并安装成功. 后来才发现,有两个BeautifulSoup的版本,一个是2012 ...

  8. poj 3268 Silver Cow Party(最短路)

    Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17017   Accepted: 7767 ...

  9. Umbraco Forms 中的Recaptcha遇到的问题

    在Umbraco Form中添加Recaptcha时,不能把它设置成Mandatory, 否则就会出错

  10. UVA 11426 GCD - Extreme (II) (欧拉函数+筛法)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70017#problem/O 题意是给你n,求所有gcd(i , j)的和,其中 ...