wait()、notify()方法原理,以及使用注意事项
wait、notify原理
在前面以经说到对象锁的本质,实际上是对象头的一个监视器锁的数据结构。这个结构如下:

(图片来源于网络)
几个线程一起竞争对象的锁(enter),只有一个能成功(acquire),成功的线程记录在The Owner结构中。调用wait、notify运行流程如下:
(1) 现有一个对象o,锁正在被线程 t1 持有,调用wait()方法后,线程 t1 将会被"晾到" (实际上仅仅是记录到) Wait Set 结构中。
(2)然后将会有另一个线程 t2 获取到锁,The Owner记录的变成了 t2 线程。
(3)t2 线程不需要 o的锁时,调用o.notify()/o.notifyAll()方法,对象o就会告诉 Wait Set结构中记录的线程们:你们又可以来竞争我啦,我的锁现在没被人持有。
简单的说就是:wait是对象通知持有自己锁的线程释放我的锁,notify()/notifyAll()就是对象通知刚刚被自己晾在一边的线程又可以来竞争我的锁了。我想到了一个比较贴切的比喻:
客人(线程)来拜访主人(对象),必须获得主人的时间权(锁),且主人同时只能接待一人(互斥)。
正在客厅接待一名客人时,因为一些原因主人必须先接待另一位客人,这时主人请当前客人去另一间房里等待,让出自己的时间权(wait方法)
主人在客厅接待另一位客人,接待完毕后,让前一位(也可能有几位)在另一间房等待的客人再来到客厅,继续接待(notify/notifyAll方法)
wait、notify要放在同步块中
其实很简单,如果不在同步块中,线程都没有取得对象的锁,又谈何让对象通知线程释放锁、或者来竞争锁呢?也许就通知到Main线程了。如果确实不放到同步块中,则会产生 Lost-wake的问题,即丢失唤醒,以上一篇中生产者消费者例子来说:
生产者线程发现箱子满了确定必须等待,但是由于wait没在同步块中,由于生产者线程此时还没有等待。
消费者线程从缓冲区消费一个产品后调用notify()方法,上个notify消息将被忽略。
生产者线程调用wait()方法并进入等待状态,得不到通知了。
因此,由于这里的竞争条件,我们可能在丢失一个通知,如果我们使用缓冲区或者只有一个产品,生产者线程将永远等待,你的程序也就挂起了。
wait()、notify()方法原理,以及使用注意事项的更多相关文章
- 【细语】C#之扩展方法原理及其使用
1.写在前面 今天群里一个小伙伴问了这样一个问题,扩展方法与实例方法的执行顺序是什么样子的,谁先谁后(这个问题会在文章结尾回答).所以写了这边文章,力图从原理角度解释扩展方法及其使用. 以下为主要内容 ...
- Java使用wait() notify()方法操作共享资源
Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写. 2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线 ...
- 并发编程之 wait notify 方法剖析
前言 2018 元旦快乐. 摘要: notify wait 如何使用? 为什么必须在同步块中? 使用 notify wait 实现一个简单的生产者消费者模型 底层实现原理 1. notify wait ...
- Java使用wait() notify()方法操作共享资源详解_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方 ...
- 高并发之wait notify notifyAll原理详解
public class WaitTest { public void testWait(){ System.out.println("Start-----"); try { wa ...
- java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader
1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...
- join方法原理
join()方法--原理同wait方法 如果不知道保护性暂停是啥的可以参考一下上一篇文章 https://www.cnblogs.com/duizhangz/p/16222854.html join方 ...
- java多线程详解(6)-线程间的通信wait及notify方法
Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...
- [转]js中几种实用的跨域方法原理详解
转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...
随机推荐
- springboot的邮件服务
作者:纯洁的微笑出处:http://www.ityouknow.com/ 版权归作者所有,转载请注明出处 springboot仍然在狂速发展,才五个多月没有关注,现在看官网已经到1.5.3.RELEA ...
- Hadoop自学系列集(三) ---- Hadoop安装
这节就开始讲述Hadoop的安装吧.在这之前先配置下SSH免密码登录,为什么需要配置这个呢?大家都知道Hadoop集群中可能有几十台机器甚至是上千台机器,而每次启动Hadoop都需要输入密码才能够登录 ...
- Web前端三大框架_angular.js 6.0(二)
Web前端三大框架_angular.js 6.0(一) 需要视频教程,看头像昵称处 一.Angular 6.0 1.1样式 html中引入样式:内嵌式,外链式,行内式. ng6中组件引入样式的方式也 ...
- Linux学习笔记07之shell
shell从广义上分为两类: GUI:GNOME KDE XFACE等 CLI:sh csh bash shell启动:当用户登录完成后,系统会自动启动shelll程序 进程:应用程序的副本,用PID ...
- spring boot中的声明式事务管理及编程式事务管理
这几天在做一个功能,具体的情况是这样的: 项目中原有的几个功能模块中有数据上报的功能,现在需要在这几个功能模块的上报之后生成一条消息记录,然后入库,在写个接口供前台来拉取消息记录. 看到这个需求,首先 ...
- 解决:django.db.utils.OperationalError: unable to open database file
这是一个从GitHub上下载的,一个网站项目的源码.想要在自己的电脑上运行,期间过程相当曲折,不过至此终于是完成了. 1.安装过程: python2->virtualenv->django ...
- Wtm携手LayUI -- .netcore 开源生态我们是认真的!
经过WTM团队和LayUI团队多次深入协商,双方于2019年7月29日在北京中国国际展览中心正式达成战略合作意向, 双方签署了战略合作框架协议,LayUI团队承诺使用WTM框架的任何项目都可以免费使用 ...
- .NET Core 3.0预览版7中的ASP.NET Core和Blazor更新
.NET Core 3.0 Preview 7现已推出,它包含一系列ASP.NET Core和Blazor的新更新. 以下是此预览中的新功能列表: 最新的Visual Studio预览包括.NET C ...
- C#连接SQL Anywhere 12 数据库
using System;using System.Data.Common; namespace ConsoleApplication27{ class Program { ...
- zookeeper 集群配置
安装前要先确保配置好 jdk,这里不在讲述 一. 将zookeeper 安装包下载到你想要的目录 下载地址:http://mirrors.hust.edu.cn/apache/zookeeper/ m ...