1.通信就是指相互交换一些数据或者发送一些控制指令,比如一个线程给另一个暂停执行的线程发送一个恢复执行的指令。

可变共享变量是天然的通信媒介,也就是说一个线程如果想和另一个线程通信的话,可以修改某个在多线程间共享的变量,另一个线程通过读取这个共享变量来获取通信的内容。

2.这里边就不得不提wait/notify机制了:

当一个线程获取到锁之后,如果发现条件1不满足,那就主动让出锁(ps:wait使当前线程让出对象锁x1,即x1.wait()),然后把这个线程放到一个等待队列等待去,等到其他某个线程把这个条件1变成ture之后,就通知等待队列里的线程他们等待的条件满足了,可以继续运行啦(ps:通知某个等待线程竞争到锁之后,进入就绪状态,等待时间片再运行)

java里规定了每一个锁都对应了一个等待队列,也就是说如果一个线程在获取到锁之后发现某个条件不满足,就主动让出锁然后把这个线程放到与它获取到的锁对应的那个等待队列里,另一个线程在完成对应条件时需要获取同一个锁,在条件完成后通知它获取的锁对应的等待队列(ps:对象锁x1.notify())。这个过程意味着锁和等待队列建立了一对一关联。

3.代码格式如下:

//wait格式
synchronized (对象) {
处理逻辑(可选)
while(条件不满足) {
对象.wait();
}
处理逻辑(可选)
}
  1. 获取对象锁。

  2. 如果某个条件不满足的话,调用锁对象的wait方法,被通知后仍要检查条件是否满足。

  3. 条件满足则继续执行代码

//notify格式
synchronized (对象) {
完成条件
对象.notifyAll();、
} 静态同步方法的锁对象可以是该类的`Class对象`,成员同步方法的锁对象可以是`this对象`。
  1. 获得对象的锁。

  2. 完成条件。

  3. 通知在等待队列中的等待线程。

4.误区分析

  误区-1:为什么必须在同步代码块中调用wait、 notify或者notifyAll方法。

  wait和notify作用于多个线程,彼此之间是互斥的,使用同步确保原子性操作,如果不使用的话,可能会出现如下执行情况

  

也就是说当等待线程已经判断条件不满足,正要执行wait方法,此时通知线程抢先把条件完成并且调用了notify方法,之后等待线程才执行到wait方法,这会导致等待线程永远停留在等待队列而没有人再去notify它。所以等待线程中的判断条件是否满足、调用wait方法和通知线程中完成条件、调用notify方法都应该是原子性操作,彼此之间是互斥的,所以用同一个锁来对这两个原子性操作进行同步,从而避免出现等待线程永久等待的尴尬局面。

另外不加锁使用的话,对象.wait();运行会抛出IllegalMonitorStateException异常

并且不能随便调用某个对象的wait,对象一定要跟同步对象一致:

synchronized (对象1) {
while(条件不满足) {
对象2.wait(); //随便调用一个对象的wait方法
}
} synchronized (对象1) {
完成条件
对象2.notifyAll();
}
对于代码对象2.wait(),表示让出当前线程持有的对象2的锁,而当前线程持有的是对象1的锁,所以这么写是错误的,也会抛出IllegalMonitorStateException异常的。意思就是如果当前线程不持有某个对象的锁,那它就不能调用该对象的wait方法来让出该锁。所以如果想让等待线程让出当前持有的锁,只能调用对象1.wait()。然后这个线程就被放置到与对象1相关联的等待队列中,在通知线程中只能调用对象1.notifyAll()来通知这些等待的线程了。

误区2-在等待线程判断条件是否满足时,应该使用while,而不是if。

这个是因为在多线程条件下,可能在一个线程调用notify之后立即又有一个线程把条件改成了不满足的状态,之后调用wait的线程获得cpu和锁,开始执行,当前条件是不满足的,肯定不能往下执行,还需要再 走一次while条件验证,满足条件才继续往下执行,不满足的话继续wait。并且整个同步代码块执行完,才会释放锁,单独调用notify是不会释放锁的。

 

    

线程间通信wait和notify【All】简介的更多相关文章

  1. Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.我们来看下相关定义: w ...

  2. Java 如何实现线程间通信?(notify、join、CountdownLatch、CyclicBarrier、FutureTask、Callable )

    转自:https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247486499&idx=1&sn=d3f2d6959df ...

  3. (三)(1)线程间通信---wait和notify的使用

    这篇博客记录线程间通信相关api使用以及理解. 首先第一点,我之前的博客里的线程之间也是通信的,但是他们的通信是建立在访问的是同一个变量上的,相当于是变量.数据层面上的通信,而下面要讲的是线程层面上的 ...

  4. 线程间通信--wait和notify

    使用wait.notify方法实现线程间的通信(注意这两个方法都是object的类的方法,换句话说java为所有的对象都提供了这两个方法) 1.wait和notify必须配合synchronized关 ...

  5. Java并发编程:线程间通信wait、notify

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  6. wait、notify、notifyAll实现线程间通信

    在Java中,可以通过配合调用Object对象的wait()方法和notify()方法或notifyAll()方法来实现线程间的通信.在线程中调用wait()方法,将阻塞等待其他线程的通知(其他线程调 ...

  7. java线程基础巩固---线程间通信快速入门,使用wait和notify进行线程间的数据通信

    之前已经对于线程同步相关的知识点进行了详细的学习,这次来学习一下线程间的通信相关的知识,话不多说直接用代码进行演练,以一个简陋的生产者消费者模型来初步了解下线程间通信是怎么一回事. 生产消费者第一版: ...

  8. 06_Java多线程、线程间通信

    1. 线程的概念      1.1多进程与多线程 进程:一个正在执行的程序.每个进程执行都有一个执行顺序,该顺序是一个执行路径,或叫一个控制单元. 一个进程至少有一个线程. 线程:就是进程中的一个独立 ...

  9. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

随机推荐

  1. create react app遇到的问题

    我现在想的是吧 static 资源和动态 api 来分开处理, static 资源开启 nginx 服务器,api 请求由 express 完成, 现在的问题是开发的时候 proxy 设定将所有的请求 ...

  2. windows 远程连接“发生身份验证错误 要求的函数不受支持”

    Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\P ...

  3. 判断JS的数据类型

    typeof.instanceof. constructor. prototype方法比较 (摘自如何判断JS中的数据类型) 1. 使用typeof操作符. 对一个值使用 typeof 操作符可能返回 ...

  4. Django中操作Redis

    一 创建redis连接池 redis_pool.py pool = redis.ConnectionPool(host='10.211.55.4', port=6379) 二 引入连接池 import ...

  5. 快速创建IIS站点并设置权限

     net user WebSiteUser WebSiteUserWebSiteUser /add /yWMIC Path Win32_UserAccount Where Name="Web ...

  6. 23. pt-slave-delay

    略过,用原生的延迟复制: stop slave; change master to master_delay=5; start slave;

  7. 设计模式学习心得<单利模式 Singleton>

    概述 意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 主要解决 一个全局使用的类频繁地创建与销毁. 何时使用 当您想控制实例数目,节省系统资源的时候. 如何解决 判断系统是否已经有这个单 ...

  8. java 给任务传递参数

    之前https://www.cnblogs.com/kexb/p/10228369.html没有参数,这里介绍参数什么传入 package com.hra.riskprice; import com. ...

  9. 状态机学习(六)解析JSON2

    来自 从零开始的 JSON 库教程 从零开始教授如何写一个符合标准的 C 语言 JSON 库 作者 Milo Yip https://zhuanlan.zhihu.com/json-tutorial ...

  10. ubuntu 应用添加进环境变量

    BG:公司同事使用的电脑系统大多为windows ,有部分mac和Ubuntu(我就是那个部分Ubuntu),某些情况为了统一格式,便下载了一些解压即可使用的软件,但是每次点开文件夹然后点开程序很繁琐 ...