首页 > 编程语言 >详解 Java多线程带来的的风险-线程安全

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

时间:2024-03-31 14:30:46浏览次数:35  
标签:Java 线程 内存 共享 多线程 CPU

目录

一、什么是线程安全?

 二、线程不安全的原因

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

标签:Java,线程,内存,共享,多线程,CPU
From: https://blog.csdn.net/2201_75437633/article/details/137198968

相关文章

  • 解析两大Java框架:Spring与Spring Boot的区别
    Spring框架基本介绍Spring是一个开源的Java平台,它最初是为了解决企业级应用开发的复杂性而创建的。作为一个全面的编程和配置模型,Spring提供了一个框架,让开发者可以构建轻量级、松耦合的应用。SpringBoot基本介绍SpringBoot是基于Spring的一个框架,设计理念是简化新Sp......
  • 【Java编程】【算法面试题】【数组轮转】给定一个整数数组 nums,将数组中的元素向右轮
    原题:给定一个整数数组nums,将数组中的元素向右轮转k个位置,其中k是非负数。例如:nums=[1,0,-1,2,3]k=1预期结果:nums=[3,1,0,-1,2]k=2预期结果:nums=[2,3,1,0,-1]以此类推。。。【本文思路解析】:1.不实用额外的数组,会多一部分开销;2.每次轮转,位置移动1位,共计移......
  • 会员制医疗预约服务管理信息系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运
    本项目包含可运行源码+数据库+LW,文末可获取本项目的所有资料。推荐阅读100套最新项目持续更新中.....2024年计算机毕业论文(设计)学生选题参考合集推荐收藏(包含Springboot、jsp、ssm+vue等技术项目合集)1.系统功能模块2.管理员功能模块......
  • 财务管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计
    本项目包含可运行源码+数据库+LW,文末可获取本项目的所有资料。推荐阅读100套最新项目持续更新中.....2024年计算机毕业论文(设计)学生选题参考合集推荐收藏(包含Springboot、jsp、ssm+vue等技术项目合集)目录1.管理员功能效果图1.1.员工功能模块2.系统功能设计3.数据库E......
  • java毕业设计基于微信公交查询小程序设计与实现
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着移动互联网技术的飞速发展,智能手机已经成为人们日常生活中不可或缺的一部分。微信作为国内领先的即时通讯软件,其小程序功能为用户提供了便捷的服务和......
  • JAVA注解-ElementType详解
    ava中元注解(用来标识注解的注解)有四个: @Retention@Target@Document@Inherited; @Retention:注解的保留位置@Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含@Retention(RetentionPolicy.......
  • 基于java+springboot+vue实现的房屋租赁系统(文末源码+Lw+ppt)23-397
    摘要随着社会的不断进步与发展,人们经济水平也不断的提高,于是对各行各业需求也越来越高。特别是从2019年新型冠状病毒爆发以来,利用计算机网络来处理各行业事务这一概念更深入人心,由于工作繁忙以及疫情的原因,用户到房源公司进行房屋求租也是比较难实施的。如果开发一款房屋租赁......
  • 基于java+springboot+vue实现的付费自习室管理系统(文末源码+Lw+ppt)23-400
    摘 要付费自习室管理系统采用B/S架构,数据库是MySQL。网站的搭建与开发采用了先进的java进行编写,使用了springboot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。主要功能包括:个人信息修改,对用户信息、自习室准则、自习室、自习计划、留言反馈、订单等功能进行......
  • 基于java+springboot+vue实现的房屋租赁系统(文末源码+Lw+ppt)23-397
    摘要随着社会的不断进步与发展,人们经济水平也不断的提高,于是对各行各业需求也越来越高。特别是从2019年新型冠状病毒爆发以来,利用计算机网络来处理各行业事务这一概念更深入人心,由于工作繁忙以及疫情的原因,用户到房源公司进行房屋求租也是比较难实施的。如果开发一款房屋租赁......
  • 基于java+springboot+vue实现的付费自习室管理系统(文末源码+Lw+ppt)23-400
     摘 要付费自习室管理系统采用B/S架构,数据库是MySQL。网站的搭建与开发采用了先进的java进行编写,使用了springboot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。主要功能包括:个人信息修改,对用户信息、自习室准则、自习室、自习计划、留言反馈、订单等功能进......