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()方法原理,以及使用注意事项的更多相关文章

  1. 【细语】C#之扩展方法原理及其使用

    1.写在前面 今天群里一个小伙伴问了这样一个问题,扩展方法与实例方法的执行顺序是什么样子的,谁先谁后(这个问题会在文章结尾回答).所以写了这边文章,力图从原理角度解释扩展方法及其使用. 以下为主要内容 ...

  2. Java使用wait() notify()方法操作共享资源

    Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写. 2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线 ...

  3. 并发编程之 wait notify 方法剖析

    前言 2018 元旦快乐. 摘要: notify wait 如何使用? 为什么必须在同步块中? 使用 notify wait 实现一个简单的生产者消费者模型 底层实现原理 1. notify wait ...

  4. Java使用wait() notify()方法操作共享资源详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 Java多个线程共享资源: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方 ...

  5. 高并发之wait notify notifyAll原理详解

    public class WaitTest { public void testWait(){ System.out.println("Start-----"); try { wa ...

  6. java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader

    1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...

  7. join方法原理

    join()方法--原理同wait方法 如果不知道保护性暂停是啥的可以参考一下上一篇文章 https://www.cnblogs.com/duizhangz/p/16222854.html join方 ...

  8. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  9. [转]js中几种实用的跨域方法原理详解

    转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...

随机推荐

  1. python网络爬虫(14)使用Scrapy搭建爬虫框架

    目的意义 爬虫框架也许能简化工作量,提高效率等.scrapy是一款方便好用,拓展方便的框架. 本文将使用scrapy框架,示例爬取自己博客中的文章内容. 说明 学习和模仿来源:https://book ...

  2. 写这篇博客之前,我又忘了“==”和equals的区别。

    没错.嘟嘟又把==号和equals 的区别给忘掉了 ==号比较基本类型的时候比的是值,比较引用类型的时候比较的是地址.equals比较基本类型的时候.... 脑子里关于这道题的答案好模糊好没有安全感 ...

  3. 基于V2EX API的nodejs组件.

    今天又学习到了新的知(zi)识(shi),来给自己做个笔录,也算在这酷热的天气里给自己写了一篇降温的‘膏药’,话就讲这么多了 ,start off...... 首先 ,依赖选择: /**设置为严格模式 ...

  4. Cookie和Session的使用详解

    我们在使用接口请求时经常听到Cookie和Session的知识,那么它们的实际意义和使用场景在哪里呢 ?    介绍如下 一.首先需要了解的是为什么需要有Cookie和Session这两个东西:Htt ...

  5. ORM详解

    讲解对象:ORM详解 作者:融水公子 rsgz 1 前言:开发流程正常只有简单的几步 0.1 配置数据库 0.2 定义模型 0.3 迁移文件 0.4 执行迁移生成数据表 0.5 使用模型类增删改查 2 ...

  6. python 处理json数据

    python 处理 json数据 以下是登录账号后获取的json数据,headers中注意加入cookie值 需要处理的数据如下: 全部代码如下 #!/usr/bin/env python # -*- ...

  7. 蓝桥杯 2n皇后问题 深搜

    默认大家会了n皇后问题 基础练习 2n皇后问题   时间限制:1.0s   内存限制:512.0MB     问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和 ...

  8. 【pycharm】Pycharm对 axios语法的支持问题

    问题: 解决办法: 1,找到pychar的settings 2,ECMAScript6

  9. EditText 使用详解

    极力推荐文章:欢迎收藏 Android 干货分享 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 一.EditText 继承关系 二.EditText 常用 ...

  10. Lua语言学习

    1,语法 语句不用分号结尾 function ... end if .. else .. end 2, io库, string库, table库, OS库, 算术库, debug库 3, dofile ...