【JavaEE初阶】多线程(4)

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~



目录

线程安全的 第四个原因

代码举例:

分析原因

解决方法

方法1

方法2 

wait(等待)和notify(通知)

wait和sleep区别


线程安全的 第四个原因

内存可见性,引起的线程安全问题

比如: 一个线程修改,另一个线程读取

代码举例:

import java.util.Scanner;

public class Demo13 {
    public static int n=0;
    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            while(n==0){
                //啥也不写
            }
            System.out.println("t1线程结束循环");
        });

        Thread t2 = new Thread(()->{
           Scanner scanner =new Scanner(System.in);
            System.out.println("请输入一个整数: ");
            n= scanner.nextInt();
        });

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

上述代码中通过线程t2将n的值修改成 非0值,按代码逻辑t1应该结束循环了,但实际上循环还在继续...

分析原因

内存可见性问题,本质上是编译器/ JVM对代码进行优化的时候,优化出了bug,如果代码是单线程的,编译器的代码优化一般都是非常准确的,优化之后不会影响到逻辑

但是代码如果是多线程的,编译器的优化就可能出现误判,导致不该优化的地方也给优化了

解决方法

方法1

加上sleep,增加开销,让编译器不启用优化

方法2 

在变量n的前面 加上volatil关键字(volatil 修饰一个变量,提示编译器这个变量是"易变的")

编译器进行上述优化的前提 是编译器认为,针对这个变量的频繁读取,结果都是固定的

但是volatile 只能解决内存可见性问题,不能解决原子性问题(如果两个线程针对同一个变量进行修改,volatile无能为力)

wait(等待)和notify(通知)

多给线程需要控制线程之间 执行某个逻辑的先后顺序,可以使用wait让 后执行的逻辑等待,完成某些逻辑之后 通过notify唤醒对应的wait

通过wait和notify可以解决'线程饿死'问题

  • wait包含 三个操作:解锁和阻塞等待(这两个操作同时进行(在内部已经打包成原子的),阻塞就是为了收到通知),接收到通知后唤醒,并且重新尝试获取锁
  • notify 是通知wait的线程被唤醒(使用 另一个线程调用)

import java.util.Scanner;

public class Demo21 {
    private static Object locker = new Object();

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

        Thread t2 = new Thread(() -> {
            System.out.println("t2 notify 之前");
            Scanner scanner = new Scanner(System.in);
            scanner.next(); // 此处用户输入啥都行, 主要是通过这个 next, 构造 "阻塞"

            synchronized (locker) {
                locker.notify();
            }

            System.out.println("t2 notify 之后");
        });

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

 

在多线程中,一个线程加锁,另一个线程加锁是无意义的,不会有任何阻塞效果 

 wait和notify使用之前都需要确保 先加锁(都需要搭配synchronized使用),才能执行

  • wait默认是"死等"(如果没有notify通知,就会一直等待)
  • wait还提供带参数的版本,指定最大时间(如果wait达到了最大的时间,还没有notify,就不会继续等待了,而是直接继续执行)

wait和sleep区别

假如 多个线程都在同一个对象上wait,此时notify 会随机 唤醒其中的一个线程,而notifyAll会唤醒所有等待的线程  ,大部分情况使用notify一个一个唤醒(多次执行notify),目的是 整个程序执行的过程是比较有序的,如果一下全部唤醒,这些被唤醒的线程会 无序的竞争锁

如果 notify 通知时,无线程wait,不会有任何副作用.

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

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

相关文章

CloudXR 套件扩展 XR 工作流

NVIDIA为开发者提供了一个先进的平台,开发者可以在该平台上使用全新NVIDIA CloudXR 套件来创建可扩展、品牌化的定制扩展现实(XR)产品。 NVIDIA CloudXR 套件基于全新架构而打造,是扩展XR生态的重要工具。它为开发者、专业人士和…

彻底理解浅拷贝和深拷贝

目录 浅拷贝实现 深拷贝实现自己手写 浅拷贝 浅拷贝是指创建一个新对象,这个对象具有原对象属性的精确副本 基本数据类型(如字符串、数字等),在浅拷贝过程中它们是通过值传递的,而不是引用传递,修改值并不…

Git项目管理工具

分布式版本控制系统

数据集 wider person 户外密集行人检测 >> DataBall

数据集 wider person 用于野外密集行人检测的多样化数据集 行人检测 目标检测 户外密集行人检测的多样化数据集 WiderPerson: A Diverse Dataset for Dense Pedestrian Detection in the Wild article{zhang2019widerperson, Author {Zhang, Shifeng and Xie, Yiliang and Wa…

常用环境部署(二十)——docker部署OpenProject

一、安装Docker及Docker-compose https://blog.csdn.net/wd520521/article/details/112609796 二、docker拉取OpenProject镜像 1、拉取镜像 docker pull openproject/openproject:14 注意: 拉取镜像的时候会有超时的现象出现,大家重新拉取几次就行…

链式二叉树的基本操作(C语言版)

目录 1.二叉树的定义 2.创建二叉树 3.递归遍历二叉树 1)前序遍历 2)中序遍历 3)后序遍历 4.层序遍历 5.计算节点个数 6.计算叶子节点个数 7.计算第K层节点个数 8.计算树的最大深度 9.查找值为x的节点 10.二叉树的销毁 从二叉树…

分贝转换 1 mVpp = 9.03dBmV

分贝转换 1 mVpp 9.03dBmV 函数发生器调节如下参数在频谱仪器上能看到9.03dBmv的电压值函数发生器产生 30mVpp 频谱仪会显示多少dBmV 函数发生器调节如下参数 输出频率:10 MHz 波形类型:正弦波 阻抗:50 Ω 幅度:1 mVpp …

【计算机网络 - 基础问题】每日 3 题(六)

✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…

回溯-重新安排行程

1.排序 Collections.sort(list,(o1, o2)-> o1.get(0).compareTo(o2.get(0))); 2.返回值 3.往集合添加元素 Arrays.asList(元素) List<List<String>> list new ArrayList<>();List<String> path new ArrayList<>();// 将[["JFK"…

影刀RPA实战:网页爬虫之CSDN博文作品数据

今天我们使用影刀来采集网页数据&#xff0c;影刀RPA是一款功能强大的自动化办公软件&#xff0c;它可以模拟人工的各种操作&#xff0c;帮助企业自动处理大量重复性、有逻辑规则的工作。影刀RPA在网页数据采集方面表现出色&#xff0c;能够实现对任何桌面软件、Web程序的自动化…

Python基础语法(1)上

常量和表达式 我们可以把 Python 当成一个计算器&#xff0c;来进行一些算术运算。 print(1 2 - 3) print(1 2 * 3) print(1 2 / 3) 这里我们可能会有疑问&#xff0c;为什么不是1.6666666666666667呢&#xff1f; 其实在编程中&#xff0c;一般没有“四舍五入”这样的规则…

第 13 章 兵马未动,粮草先行——InnoDB 统计数据是如何收集的

表的统计数据&#xff1a;SHOW TABLE STATUS LIKE table_name; 索引的统计数据&#xff1a;SHOW INDEX FROM table_name; 13.1 两种不同的统计数据存储方式 InnoDB 提供了两种存储统计数据的方式&#xff1a; 永久性的统计数据。存储在磁盘上&#xff0c;服务器重启之后还在…

华为 HCIP 认证费用和报名资格

在当今竞争激烈的信息技术领域&#xff0c;华为 HCIP认证备受关注。它不仅能提升个人的技术实力与职业竞争力&#xff0c;也为企业选拔优秀人才提供了重要依据。以下将详细介绍华为 HCIP 认证的费用和报名资格。 一、HCIP 认证费用 华为HCIP认证的费用主要由考试费和培训费构成…

Maven下载安装

下载 下载地址&#xff1a;Maven – Download Apache Maven 选择合适的版本进行下载 windows&Linux安装 1, 解压apache-maven-3.6.1.rar即安装完成 2&#xff0c; 配置环境变量MAVEN_HOME为安装路径&#xff0c;并将MAVEN_HOME的bin目录配置到PATH下 3&#xff0c;…

C#命令行参数解析库System.CommandLine介绍

命令行参数 平常在日常的开发过程中&#xff0c;会经常用到命令行工具。如cmd下的各种命令。 以下为sc命令执行后的截图&#xff0c;可以看到&#xff0c;由于没有输入任何附带参数&#xff0c;所以程序并未执行任何操作&#xff0c;只是输出了描述和用法。 系统在创建一个新…

最佳实践 · MySQL 分区表实战指南

引言 在数据量急剧增长的今天&#xff0c;传统的数据库管理方式可能无法有效处理海量数据的存储和查询需求。MySQL 提供了分区表功能&#xff0c;这不仅能够帮助优化性能&#xff0c;还能简化数据管理过程。分区表允许将数据表拆分成多个逻辑上的分区&#xff0c;每个分区可以…

资源管理新视角:利用 FastAPI Lifespan 事件优化你的应用II

本文说明在 FastAPI 应用程序中使用 lifespan 事件来管理资源的加载和卸载。lifespan 事件允许你在应用启动时执行一些初始化代码&#xff0c;并在应用关闭时执行一些清理代码。这是通过使用异步上下文管理器实现的&#xff0c;具体来说&#xff0c;是通过 asynccontextmanager…

什么是职场?职场的本质又是什么呢?

最近&#xff0c;经常看到很多职场相关的&#xff0c;比如职场必备技能、职场人际关系、职场晋升等等&#xff0c;这些都是职场的一些方面&#xff0c;但是却少有人来深入剖析什么是职场&#xff0c;职场的本质又是什么&#xff0c;今天我们就来一起来聊一聊&#xff0c;到底职…

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

一、引言 通过FFmpeg命令&#xff1a; ./ffmpeg -i XXX.aac 可以判断出某个文件是否为AAC裸流文件&#xff1a; 所以FFmpeg是怎样判断出某个文件是否为AAC裸流文件呢&#xff1f;它内部其实是通过adts_aac_probe函数来判断的。从《FFmpeg源码&#xff1a;av_probe_input_for…

性能测试的复习3-jmeter的断言、参数化、提取器

一、断言、参数化、提取器 需求&#xff1a; 提取查天气获取城市名请求的响应结果&#xff1a;城市对查天气获取城市名的响应结果进行响应断言和json断言对查天气获取城市名添加用户参数 1、步骤 查看天气获取城市名 json提取器&#xff08;对响应结果提取、另一个接口请求…