详解 Java多线程带来的的风险-线程安全

目录

一、什么是线程安全?

 二、线程不安全的原因

1、线程调度是随机的

2、修改共享数据:多个线程修改同⼀个变量

3、原⼦性  ​编辑

(1)什么是原⼦性

(2)⼀条 java 语句不⼀定是原⼦的,也不⼀定只是⼀条指令 

(3)不保证原⼦性会给多线程带来什么问题

(4)可⻅性:可⻅性指, ⼀个线程对共享变量值的修改,能够及时地被其他线程看到.

(5)Java 内存模型 (JMM) 

 1) 初始情况下, 两个线程的⼯作内存内容⼀致.

​编辑 2) ⼀旦线程1 修改了 a 的值, 此时主内存不⼀定能及时同步. 对应的线程2 的⼯作内存的 a 的值也不⼀定能及时同步.

此时引⼊了两个问题:

1) 为啥整这么多内存?

2) 为啥要这么⿇烦的拷来拷去?

4、指令重排序


引言:

        在 Java 编程中,线程安全是一个至关重要的概念。当多个线程同时访问共享的资源时,如果没有适当的同步措施,就会出现数据竞争和不一致的情况,从而导致程序出现各种难以预料的错误。因此,理解并处理线程安全问题是编写高质量、可靠性强的 Java 程序的关键。

一、什么是线程安全?

        线程安全是指在多线程环境中,对共享资源的访问不会导致数据的损坏或不一致。一个线程安全的程序在多线程环境下执行时,能够确保各个线程都能正确地操作共享的数据,而不会产生意外结果。

 二、线程不安全的原因

1、线程调度是随机的

这是线程安全问题的 罪魁祸⾸
随机调度使⼀个程序在多线程环境下, 执⾏顺序存在很多的变数.
程序猿必须保证 在任意执⾏顺序下 , 代码都能正常⼯作.

2、修改共享数据:多个线程修改同⼀个变量

3、原⼦性  

(1)什么是原⼦性
我们把⼀段代码想象成⼀个房间,每个线程就是要进⼊这个房间的⼈。如果没有任何机制保证,A进⼊ 房间之后,还没有出来;B 是不是也可以进⼊房间,打断 A 在房间⾥的隐私。这个就是不具备原⼦性 的。
那我们应该如何解决这个问题呢?是不是只要给房间加⼀把锁,A 进去就把⻔锁上,其他⼈是不是就进不来了。这样就保证了这段代码的原⼦性了。
有时也把这个现象叫做同步互斥,表⽰操作是互相排斥的。
(2)⼀条 java 语句不⼀定是原⼦的,也不⼀定只是⼀条指令 
⽐如刚才我们看到的 n++,其实是由三步操作组成的:
  1. 从内存把数据读到 CPU
  2. 进⾏数据更新
  3. 把数据写回到 CPU
(3)不保证原⼦性会给多线程带来什么问题
如果⼀个线程正在对⼀个变量操作,中途其他线程插⼊进来了,如果这个操作被打断了,结果就可能是错误的。 这点也和线程的抢占式调度密切相关. 如果线程不是 "抢占" 的, 就算没有原⼦性, 也问题不⼤.
(4)可⻅性:可⻅性指, ⼀个线程对共享变量值的修改,能够及时地被其他线程看到.
(5)Java 内存模型 (JMM) 
Java虚拟机规范中定义了Java内存模型.
⽬的是屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到⼀致的并发效果.

 

  • 线程之间的共享变量存在 主内存 (Main Memory).
  • 每⼀个线程都有⾃⼰的 "⼯作内存" (Working Memory) .
  • 当线程要读取⼀个共享变量的时候, 会先把变量从主内存拷⻉到⼯作内存, 再从⼯作内存读取数据
  • 当线程要修改⼀个共享变量的时候, 也会先修改⼯作内存中的副本, 再同步回主内存.  
由于每个线程有⾃⼰的⼯作内存, 这些⼯作内存中的内容相当于同⼀个共享变量的 "副本". 此时修改线程1 的⼯作内存中的值, 线程2 的⼯作内存不⼀定会及时变化
 1) 初始情况下, 两个线程的⼯作内存内容⼀致.
 2) ⼀旦线程1 修改了 a 的值, 此时主内存不⼀定能及时同步. 对应的线程2 的⼯作内存的 a 的值也不⼀定能及时同步.

 这个时候代码中就容易出现问题.

此时引⼊了两个问题:
  • 为啥要整这么多内存?
  • 为啥要这么⿇烦的拷来拷去?
1) 为啥整这么多内存?
实际并没有这么多 "内存". 这只是 Java 规范中的⼀个术语, 是属于 "抽象" 的叫法.
所谓的 "主内存" 才是真正硬件⻆度的 "内存". ⽽所谓的 "⼯作内存", 则是指 CPU 的寄存器和⾼速缓存.
2) 为啥要这么⿇烦的拷来拷去?
因为 CPU 访问⾃⾝寄存器的速度以及⾼速缓存的速度, 远远超过访问内存的速度(快了 3 - 4 个数量级, 也就是⼏千倍, 上万倍).
⽐如某个代码中要连续 10 次读取某个变量的值, 如果 10 次都从内存读, 速度是很慢的. 但是如果只是 第⼀次从内存读, 读到的结果缓存到 CPU 的某个寄存器中, 那么后 9 次读数据就不必直接访问内存了. 效率就⼤⼤提⾼了.

 那么接下来问题⼜来了, 既然访问寄存器速度这么快, 还要内存⼲啥??

答案就是⼀个字: 贵

 值的⼀提的是, 快和慢都是相对的. CPU 访问寄存器速度远远快于内存, 但是内存的访问速度⼜远远快 于硬盘. 对应的, CPU 的价格最贵, 内存次之, 硬盘最便宜

 

4、指令重排序

什么是代码重排序
⼀段代码是这样的:
  1. 去前台取下 U 盘
  2. 去教室写 10 分钟作业
  3. 去前台取下快递
如果是在单线程情况下,JVM、CPU指令集会对其进⾏优化,⽐如,按 1->3->2的⽅式执⾏,也是没问题,可以少跑⼀次前台。这种叫做指令重排序

 编译器对于指令重排序的前提是 "保持逻辑不发⽣变化". 这⼀点在单线程环境下⽐较容易判断, 但是在多线程环境下就没那么容易了, 多线程的代码执⾏复杂程度更⾼, 编译器很难在编译阶段对代码的执⾏效果进⾏预测, 因此激进的重排序很容易导致优化后的逻辑和之前不等价.

 总结:

        在编写 Java 程序时,必须时刻牢记线程安全问题,合理使用同步机制、并发容器和原子类等工具,确保多线程环境下程序的正确性和稳定性。只有这样,才能编写出高效、健壮的多线程应用。

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

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

相关文章

【转移表】

文章目录 一、函数指针数组1.什么事函数指针数组2.函数指针数组如何定义 二、转移表结束语 一、函数指针数组 1.什么事函数指针数组 在我们学习函数指针数组前,大家可以一起回顾一下我们以前学习的指针和数组。 数组指针 数组指针是指指向数组的指针。 int arr…

每日五道java面试题之springboot篇(四)

目录: 第一题. Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?第二题. 微服务中如何实现 session 共享 ?第三题. Spring Boot 中如何实现定时任务 ?第四题. 运行 Spring Boot 有哪几种方式?第五题. 开启 Spring Boot 特性有哪几种方式&#xff1f…

MySQL - 高阶语句(一)

先准备一张表 create table class1 (id int,name varchar(10) primary key not null ,score decimal(5,2),address varchar(20),hobbid int(5));insert into class1 values(1,liuyi,80,beijing,2); insert into class1 values(2,wangwu,90,shengzheng,2); insert into class1 …

Linux是怎么发送一个网络包的?

目录 摘要 1 从 send 开始 2 传输层 3 网络层 4 网络接口层 4.1 邻居子系统 4.2 网络设备子系统 4.3 软中断发送剩余的 skb 4.4 硬中断又触发软中断 总结 摘要 一个网络包的发送,始于应用层,经层层协议栈的封装,终于网卡。今天来循…

【C语言】贪吃蛇【附源码】

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 一、游戏说明: 一个基于C语言链表开发的贪吃蛇游戏: 1. 按方向键上下左右,可以实现蛇移动方向的改变。 2. 短时间长按方向键上下左右其中之一,可实现蛇向该方向的短时间…

AndroidStudio出现类似 Could not create task ‘:app:ToolOperatorDemo.main()‘. 错误

先看我们的报错 翻译过来大概意思是:无法创建任务:app:ToolOperatorDemo.main()。 没有找到名称为“main”的源集。 解决方法&#xff1a; 在.idea文件夹下的gradle.xml文件中 <GradleProjectSettings>标签下添加<option name"delegatedBuild" value"f…

指针强化练习(详解)

更多学习内容 结构体内存对齐 和 位段-CSDN博客指针初级&#xff08;基础知识&#xff09;-CSDN博客指针进阶(深入理解)-CSDN博客 目录 1.sizeof与strlen的区别 2.一维数组 3.字符指针 4.二维数组 5.指针运算(笔试题) 6.函数指针 1.sizeof与strlen的区别 请思考以下运行结…

IntelliJ IDEA 2023 for Mac 好用的Java开发工具

IntelliJ IDEA 2023是一款由JetBrains开发的强大的集成开发环境&#xff08;IDE&#xff09;软件&#xff0c;适用于多个编程语言。它旨在提高开发人员的生产力和代码质量&#xff0c;具有以下多种特色功能&#xff1a; 软件下载&#xff1a;IntelliJ IDEA 2023 v2023.3.6中文激…

mixly编译esp32程序缺失问题bits/c++config.h

错误信息&#xff1a; 编译中... 使用平台的 ‘esp32’ 开发板&#xff0c;在列出的文件夹中&#xff1a;D:\windowsoftInstalled\mixly\mixly2.0-win32-x64\arduino-cli\Arduino15\packages\esp32\hardware\esp32\2.0.7 使用平台的 ‘esp32’ 代码&#xff0c;在列出的文件夹…

【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

使用python实现i茅台自动预约

使用python实现i茅台自动预约[仅限于学习,不可商用] 运行: 直接运行 imtApi.py 打包:切换到imt脚本目录,执行打包命令: pyinstaller --onefile imtApi.py这个应用程序可以帮助你进行茅台自动化配置。以下是一些使用说明: 平台注册账号(可用i茅台)不用登录,你可以进行…

【数据分析面试】5.地址信息数据清洗合并 (Python)

题目 有两个数据框。一个包含有关地址的信息&#xff0c;另一个包含了不同城市和州之间的关系。 示例&#xff1a; df_addresses address4860 Sunset Boulevard, San Francisco, 941053055 Paradise Lane, Salt Lake City, 84103682 Main Street, Detroit, 482049001 Casca…

hackmyvm———Quick4之tar命令注入

目录 1.信息收集 2.目录扫描 3.文件上传 ​4.提权 简介&#xff1a;HackMyVm是一个集合了大量靶机的平台&#xff0c;通过下载压缩包后导入Vm虚拟机来使用&#xff0c;推荐使用VirtualBox来导入加载漏洞虚拟机。类似于Vulnhub、HackTheBox&#xff0c;但是相比于Vulnhub而言…

利用TensorRT在jetson orin 上加速YOLOv5

一、第一种方法&#xff0c;需要下载各种包&#xff1a; 要用到一个大佬的开源&#xff0c;GitHub地址如下&#xff1a; https://github.com/wang-xinyu/tensorrtx/tree/master/yolov51. 安装pycuda&#xff0c;在线安装pycuda pip3 install pycuda 或者&#xff1a; sudo…

数据结构之单链表实现(JAVA语言+C语言)

一、理论 1 单链表结构 2 增、删、查 、改思路 &#xff08;增&#xff09;直接添加放到最后即可。按顺序添加&#xff1a;找到要修改的节点的前一个节点&#xff0c;插入新节点&#xff08;&#xff09;。&#xff08;改&#xff09;要修改的节点修改内容即可。&#xff08;…

STM32+ MAX30102通过指尖测量心率+血氧饱和度

一、前言 重要的事情放在最前面&#xff1a;max30102只适用于指尖手指测量&#xff0c;不适用与手腕手指测量&#xff0c;如需做成可穿戴样式选择传感器的小伙伴请pass掉他&#xff0c;因为他只有红光和红外2种光&#xff0c;不够充足的数据源去运算。 由于一些原因&#xff0c…

阿基米德分牛问题及其Python求解

文章目录 题目大意sympy求解结果 题目大意 问 太阳神有一牛群&#xff0c;由白、黑、花、棕四种颜色的公、母牛组成&#xff0c;其间关系如下&#xff0c;求每种牛的个数。 公牛中&#xff0c;白牛多于棕牛&#xff0c;二者之差为黑牛的 1 2 1 3 \frac{1}{2}\frac{1}{3} 21​…

排序——交换排序(冒泡排序与快速排序)

本专栏和大家分享关于排序的算法,其中有插入排&#xff08;直接插入排序和希尔排序&#xff09;、选择排序&#xff08;直接选择排序和堆排&#xff09;、交换排序&#xff08;冒泡排序和快速排序&#xff09;、归并排序以及其他非基于比较的排序 本文与大家分享交换排序 目录 …

SAP FICO 银企直联

银企直联是指企业通过互联网或专线连接的方式&#xff0c;使企业的SAP系统与商业银行的业务系统通过特定的数据接口实现连接&#xff0c;在SAP系统中可以直接查询银行账户的余额和明细&#xff0c;实现付款、银企对账、自动出具余额调节表等功能。 在这主要介绍SAP相关CALLSS配…

C++—vector的介绍及使用 vector的模拟实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用 1.2.1 vector的定义 1.2.2 vector iterator 的使用 1.2.3 vector 空间增长问题 1.2.4 vecto…