线程安全3--wait和notify

文章目录

  • wait and notify(等待通知机制
  • notify
  • 补充

wait and notify(等待通知机制

引入wait notify就是为了能够从应用层面上,干预到多个不同线程代码的执行顺序,这里说的干预,不是影响系统的线程调度策略(内核里调度线程,仍然是无序调度)
相当于是在应用程序代码中,让后执行的线程,主动放弃被调度的机会,就可以让先执行的线程,先把对应代码执行完了
举例:
在ATM机上取钱
在这里插入图片描述
ATM通过锁来互斥
第一个人,先进去,发现ATM没钱,然后出来了,但是和其他人来竞争这个ATM,参与到了锁竞争中,此时完全有可能第一个人再次拿到这个锁,如果反复如此,就会导致第一个人反复获取到锁,但又无法完成实质性的逻辑,导致“线程饿死”。
这种情况就是严重的bug,当第一个人发现自己要执行的逻辑,前提条件不具备,在这种情况下,应该主动放弃对锁的竞争,一直到条件具备,此时再解除阻塞,参与锁竞争,这个时候就要用到wait和notify
在这里插入图片描述
join是等待另一个线程执行完,才继续执行
wait则是等待另一个线程通过notify进行通知(不要求另一个线程必须执行完)
wait进入阻塞,只能说明自己释放锁了
其他线程是否拿到了锁,另当别论

阻塞产生的原因有好几种:
1.sleep TIMED_WAITING
2.join/wait WAITING
3.synchronized BLOCKED

Object object = new Object();
        object.wait();

随便拿一个对象都能调用wait但是运行起来会报异常
在这里插入图片描述
不合法监视状态异常
原因:wait一旦调用就会释放锁,释放锁的前提是拿到锁,所以,wait必须放到synchronized里面使用。
wait锁对象必须和synchronized锁对象一致

public class Test4 {
    public static void main(String[] args) {
        Object object = new Object();
        Thread t1 = new Thread(()->{
            synchronized (object){
                System.out.println("wait前");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("wait后");
            }
        });
        t1.start();
    }
}

输出结果:

wait前

代码一直没有结束

在Java监视和管理控制台上:
在这里插入图片描述

notify

锁被wait就需要来唤醒锁,notify就是来唤醒锁的
notify可以不放在synchronized里面,但是Java规定notify必须放在synchronized里面

public class Test4 {
    public static void main(String[] args) throws InterruptedException {
        Object object = new Object();

      Thread t1 = new Thread(()->{
            synchronized (object){
                System.out.println("wait前");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("wait后");
            }
        });
      Thread t2 = new Thread(()->{
          try {
              Thread.sleep(2000);
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
          synchronized(object){
              System.out.println("notify前");
              object.notify();
              System.out.println("notify后");
          }
      });

        t1.start();
        t2.start();
    }
}

运行结果:

wait前
notify前
notify后
wait后

线程2使用sleep的原因
因为线程调度是随机的,不确定线程1还是线程2先运行,如果线程2先运行就达不到我们预期的结果,所以sleep线程2,让线程1先运行,先执行wait,再执行notify。

上述代码运行执行过程:
1.t1先执行起来后,就会立即拿到锁,并打印wait前,然后进入wait方法(释放锁+阻塞等待)
2.t2执行起来,先进行sleep五秒(为了让t1先拿到锁)
3.t2sleep结束后,由于t1是wait状态,锁是释放的,t2就能拿到锁,接下来打印notify前,执行notify操作,唤醒t1
4.由于t2还没有释放锁,t1想要获取锁,可能会出现阻塞,和t2锁竞争导致
5.t2打印notify后,释放锁,t2执行完毕,t1获取到锁,打印wait后

补充

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/233147.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

持续集成交付CICD:Jenkins流水线实现Nexus制品晋级策略

目录 一、理论 1.开发测试运维环境 二、实验 1.Nexus制品晋级策略 一、理论 1.开发测试运维环境 (1)环境 1)持续集成开发环境(DEV: Development Environment) 直接通过源代码编译打包,其会跑单元测试…

C# | 使用AutoResetEvent和ManualResetEvent进行线程同步和通信

使用AutoResetEvent和ManualResetEvent进行线程同步和通信 文章目录 使用AutoResetEvent和ManualResetEvent进行线程同步和通信介绍AutoResetEventManualResetEvent 异同点使用场景和代码示例AutoResetEvent 使用示例ManualResetEvent 使用示例阻塞多个线程并同时激活 介绍 在…

fl studio2024官方体验版如何破解?

fl studio2024全称Fruity Loops Studio2024,这款软件也被人们亲切的称之为水果,它是一款功能强大的音乐创作编辑软件,拥有全功能的录音室,大混音盘以及先进的音乐制作工具,用户通过使用该软件,就可以轻松制…

MySQL的锁机制

1.简介 MySQL的隔离性是由锁机制来保证的。锁是计算机协调多个进程或线程并发地访问某一资源你的机制。当多线程并发地访问某个数据时,尤其是在涉及金钱等安全敏感性数据的时候,需要保证数据在任意时刻最多只有一个线程可以对其进行修改,从而…

class070 子数组最大累加和问题与扩展-上【算法】

class070 子数组最大累加和问题与扩展-上【算法】 code1 53. 最大子数组和 // 累加和最大子数组和 // 给你一个整数数组 nums // 请你找出一个具有最大累加和的非空子数组 // 返回其最大累加和 // 测试链接 : https://leetcode.cn/problems/maximum-subarray/ dp[i]&#xff…

Aloha 机械臂的学习记录2——AWE:AWE + ACT

继续下一个阶段: Train policy python act/imitate_episodes.py \ --task_name [TASK] \ --ckpt_dir data/outputs/act_ckpt/[TASK]_waypoint \ --policy_class ACT --kl_weight 10 --chunk_size 50 --hidden_dim 512 --batch_size 8 --dim_feedforward 3200 \ --n…

如何轻松恢复 Windows 中删除的文件夹

我们都曾经历过这样的事,而且我们中的大多数人可能很快就会再次这样做。我们讨论的是在 Windows 中按“Delete”或“ShiftDelete”键意外删除重要文件夹的情况。 如果您刚刚按下删除键且未超过 30 天,或者尚未清空回收站,则可以恢复文件夹。…

uniapp获取wifi连接状态

当使用Uniapp开发移动应用时,我们经常需要获取设备的连接状态,特别是WiFi连接状态。下面是一个简短的关于在Uniapp中获取WiFi连接状态的博客: 在Uniapp中,要获取设备的WiFi连接状态,我们可以利用uni.getNetworkType接…

统信UOS_麒麟KYLINOS上跨架构下载离线软件包

原文链接:统信UOS/麒麟KYLINOS上跨架构下载离线软件包 hello,大家好啊,今天给大家带来一篇在统信UOS/麒麟KYLINOS上跨架构下载离线软件包的实用教程。在我们的日常工作中,可能会遇到这样的情况:需要为不同架构的设备下…

键盘打字盲打练习系列之反复练习——3

一.欢迎来到我的酒馆 盲打,反复练习! 目录 一.欢迎来到我的酒馆二.数字&符号键位指法1.数字键位指法2.符号键位指法 三.反复练习 二.数字&符号键位指法 前面的一个章节重点介绍了主键盘区字母键位的指法:基准键位指法、" QWERTY…

WireShark监控浏览器登录过程网络请求

软件开发中经常前后端扯皮。一种是用Chrome浏览器的开发者工具 来看网络交互,但是前提是 网络端口的确是通的。 WireShark工作在更低层。 这个工具最大的好处,大家别扯皮,看网络底层的log,到底 你的端口开没开, 数据…

idea中run和debug是灰色的

【现象】idea中run和debug是灰色的 点击 旁边的Add Configuration…一看都是空白 【解决方法】: npm点开之后 【结果】

【Java+MySQL】前后端连接小白教程

目录 🍭【IntelliJ IDEA】操作 🍭1. 连接MySQL数据库 🌈1.1 错误解决 🍭2. 操作MySQL数据库 🌈2.1 双击查看表数据 🌈2.2 编写SQL脚本 🍭【IntelliJ IDEA】 IntelliJ IDEA是由JetBrains公司…

js 复制粘贴板,当clipboardjs 不好使怎么办?

最近项目中做一个很常见的复制粘贴的功能耽误了比较长的时间特此记录&#xff0c;在往常这个功能直接用 clipboard 做就行了&#xff0c;但是这次却发现复制功能不好使了&#xff0c;虽然走了复制成功的回调&#xff0c;但是粘贴板并没有复制的内容。代码如下 <div v-for&q…

虚拟机安装 hyper—v 沙盒

一、下载系统镜像 1、确认电脑内存在8G及以上并提前准备完整的系统镜像 安装Hyper-V并重启电脑后打开程序选择虚拟机 选择安装位置并设置保留第一代的虚拟参数即可开始分配内存&#xff0c;根据自己的需求进行设置 右键虚拟机启动并开始运行&#xff0c;进行镜像系统的安装便完…

初识人工智能,一文读懂强化学习的知识文集(5)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

Python之html2text,清晰解读HTML内容!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是彭涛&#xff0c;今天为大家分享 Python之html2text&#xff0c;清晰解读HTML内容&#xff0c;全文3900字&#xff0c;阅读大约10分钟。 HTML是Web开发中常见的标记语言&#xff0c;但有时我们需要将HTML内容…

【MyBatis系列】MyBatis字符串问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

软件设计师——计算机组成原理(二)

&#x1f4d1;前言 本文主要是【计算机组成原理】——软件设计师——计算机组成原理的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 …

ffmpeg之ffprobe.c源码分析一---大流程及核心代码分析

文章目录 前言为什么学习ffprobe源码源码调试main()函数重要流程函数分析open_input_file函数分析avformat_match_stream_specifier函数分析read_packets函数分析本篇文章带你打通ffprobe源码的脉络。 关注公众号免费看: 前言 注:本文章全凭个人经验以及平时学习所记录,由…