【JavaEE初阶】线程安全(重点)

news2025/6/24 6:56:00

目录

📕 线程安全的概念

🎄 观察线程不安全

🌳 线程不安全的原因

🚩 原因:

🌲解决之前的线程不安全问题

🚩 synchronized 关键字


📕 线程安全的概念        

如果多线程环境下代码运行的结果是符合我们预期的,即在单线程环境应该的结果,则说这个程序是线程安全的。

🎄 观察线程不安全

例子:

典型的多线程并发导致的问题,如果让两个线程串行执行,就没有任何问题!!

上述问题,就是多线程在搞鬼!!!

🌳 线程不安全的原因

那么对于此图,就是可能二和可能三是能够正确执行的,因为他们是串行执行,其他情况就不行了

🚩 原因:

原子性:

原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,即不被中断操作,要不全部执行完成,要不都不执行

例子:我们把一段代码想象成一个房间,每个线程就是要进入这个房间的人。如果没有任何机制保证,A进入房间之后,还没有出来;B 是不是也可以进入房间,打断 A 在房间里的隐私。这个就是不具备原子性的。

那我们应该如何解决这个问题呢?

是不是只要给房间加一把锁,A 进去就把门锁上,其他人是不是就进不来了。这样就保证了这段代码的原子性了。

有时也把这个现象叫做同步互斥,表示操作是互相排斥的

注意:一条 java 语句不一定是原子的,也不一定只是一条指令

比如我们上述不安全的代码 count ++,其实是由三步操作组成的

  1. 从内存把数据读到 CPU
  2. 进行数据更新
  3. 把数据写回到 CPU

所以在多线程中,有可能一个线程还没自增完,可能才执行到第二步(进行数据更新),另一个线程就已经读取了值,导致结果错误。那如果我们能保证自增操作是一个原子性的操作,那么就能保证其他线程读取到的一定是自增后的数据。

🌲解决之前的线程不安全问题

结合上述整理的5条原因:

第一个原因,我们改变不了,因为内核已经是搞好了的,我们自己改也没用

第二个原因通过调整代码结构,尽量避免出现拿多个线程同时改同一个变量,这是一个切入点,但是在Java中,这种做法不是很普适,只是针对一些特定的场景是可以做到的,比如前面讲到过,String是不可变对象,StringBuffer加锁,是线程安全,StringBuilder不是线程安全

第三个原因,这是解决线程安全问题最普适的方案

针对锁进行小结:

🚩 synchronized 关键字

我们使用关键字synchronized进行加锁操作

代码:

这个代码就是两个线程针对同一个对象进行加锁!!!

此代码就是两个线程针对两个不同对象加锁,就不会产生"互斥"!!!那么线程安全问题就解决了

分析上述代码的执行过程:

首先,操作系统里面的加锁解锁功能,核心还是cpu提供的指令(硬件提供了这样的能力,软件才有对应的功能)。

代码一:

当我们把两个线程的synchronized加到for循环外面,这个情况就是t1把5w次循环循环完t2才开始算,此时for循环的条件和i++就不能并发执行了,这个代码是对的,但是好的选择(不如直接写单线程)。

关于synchronized的其他写法:

此代码本质上和上述产生线程安全的代码本质上是一样的,都是两个线程并发的针对同一个变量进行++,只不过此代码的变量用一个类包装起来了,通过add方法来进行++。结果也是一个不确定的值,此时也是刚才所谈到的线程安全问题!!!

对于此代码我们仍然也可以通过加锁来解决线程安全问题!!

还是可以搞一个Object类,通过这个对象作为锁:

观察上述代码,之前说过加锁操作,我们可以针对任意对象进行加锁,这里面已经有一个counter引用,就可以直接对这个counter进行加锁,对于这个代码,没必要在搞一个locker了。

即代码实现:

再次强调,加锁具体是针对哪个对象不重要,重要的是两个线程是否针对同一个对象进行加锁

那么既然是针对自己加锁,就可以把加锁操作在Counter类中的add方法中实现

他们之间并没有什么区别,只是上面代码针对counter加锁,下面代码synchronized括号中的this也是针对counter加锁,之前讲过,我们说this在哪个方法中,谁调用这个方法,this就指向谁,那么下面代码就是通过counter调用add,即this指向的是counter,也就是针对counter进行加锁!!!

代码:

在进一步讲,方法一进来就进行加锁,等到解锁之后,方法也就执行完了,意味着加锁的生命周期和方法的生命周期是一样的,这个时候就可以之间把synchronized写到方法上!两种写法是等价的

synchronized修饰普通方法相当于就是针对this加锁,还有个static方法,static修饰的方法没有this,synchronized修饰static放到,那么相当于就是针对该类的类对象加锁

 

上述方法代码具体例子:

this:(部分代码)

类对象:(部分代码)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端面经1

1、js是单线程还是多线程? 单线程执行。一次只能执行一个任务,处理任务的方式是通过一个任务队列(也称为消息队列)来实现的。如果某个操作(如网络请求或定时器)需要花费较长时间才能完成,它不会…

Flink SQL 的工作机制

前言 Flink SQL 引擎的工作流总结如图所示。 从图中可以看出,一段查询 SQL / 使用TableAPI 编写的程序(以下简称 TableAPI 代码)从输入到编译为可执行的 JobGraph 主要经历如下几个阶段: 将 SQL文本 / TableAPI 代码转化为逻辑执…

如何保证前后端交互信息不被篡改。

先说说前后端有哪些认证方式来保证: 基于 session 的认证方式:前端在用户登录成功后,后端会在服务器端生成一个唯一的 session ID,并将该 session ID 返回给前端,在后续的请求中,前端需要带上该 session ID…

【漏洞复现】蓝凌OA——远程命令执行

声明:本文档或演示材料仅供教育和教学目的使用,任何个人或组织使用本文档中的信息进行非法活动,均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现 漏洞描述 蓝凌OA平台,数字化向纵深发展,正加速构建产业互联…

图解分布式事务中的2PC与Seata方案

文章目录 文章导图什么是2PC解决传统2PC方案XA方案DTP模型举例:新用户注册送积分总结: Seata方案设计思想执行流程举例:新用户注册送积分 Seata实现2PC事务(AT模式)前提整体机制写隔离读隔离实际案例理解要点说明核心代…

自动驾驶-机器人-slam-定位面经和面试知识系列06之C++STL面试题(02)

这个博客系列会分为C STL-面经、常考公式推导和SLAM面经面试题等三个系列进行更新,基本涵盖了自己秋招历程被问过的面试内容(除了实习和学校项目相关的具体细节)。在知乎和牛客(某些文章上会附上内推码)也会同步更新&a…

锅总详解开源组织之ASF

ASF是什么?ASF孵化的顶级项目有哪些?ASF顶级项目商用化有哪些?涉及的版权是什么?应用案例有哪些?衍生项目及其关联是什么?希望本文能帮您解答这些疑惑! 一、ASF简介 Apache Software Foundati…

Java从入门到精通 (十一) ~ 操作系统、进程和线程

无论做什么,请记住都是为你自己而做,这样就毫无怨言!今天,我为自己而活!今天,又是美丽的一天!早安,朋友! 目录 前言 一、操作系统 1. 概念 2. 操作系统的基本功能 3…

Mindspore框架循环神经网络RNN模型实现情感分类|(五)模型训练

Mindspore框架循环神经网络RNN模型实现情感分类 Mindspore框架循环神经网络RNN模型实现情感分类|(一)IMDB影评数据集准备 Mindspore框架循环神经网络RNN模型实现情感分类|(二)预训练词向量 Mindspore框架循环神经网络RNN模型实现…

Ubuntu上编译多个版本的frida

准备工作 Ubuntu20(WSL) 略 安装依赖 sudo apt update sudo apt-get install build-essential git lib32stdc-9-dev libc6-dev-i386 -y nodejs 去官网[1]下载nodejs,版本的话我就选的20.15.1: tar -xf node-v20.15.1-linux-x64.tar.xz 下载源码 …

科研论文之Word论文编辑

这篇文章介绍在word中怎么编辑论文,包括论文的模板、论文的字体设置、论文的插图、论文的参考文献等等。 为便利知识传播,我的所有文章都不会设置收费专栏。但文章写作不易,如有可能麻烦打赏一下,金额随意。收款码见下图&#xff…

Ubuntu下手动部署Java项目

1.1 打包项目上传至Ubuntu 1.2 java -jar 项目压缩包 1.3 确认防火墙打开 1.4 令进程在后台运行 nohup java -jar boot工程.jar &> hello.log & 1.5 停止项目运行 查看进程号,杀掉进程

基于微信小程序+SpringBoot+Vue的刷题系统(带1w+文档)

基于微信小程序SpringBootVue的刷题系统(带1w文档) 基于微信小程序SpringBootVue的刷题系统(带1w文档) 本系统是将网络技术和现代的管理理念相结合,根据试题信息的特点进行重新分配、整合形成动态的、分类明确的信息资源,实现了刷题的自动化,…

axure制作切换栏--动态面板的应用

先看下效果:点击上面的切换栏 切换到西游记栏目: 切换到水浒传栏目: 上述两个图片比对可以发现,在点击切换栏的时候,里面的内容以及切换栏的下面蓝色横线也会发生对应的变化。这里涉及到两个地方的变化,就…

VirtualBox虚拟机安装,Ubuntu iso 镜像下载

利用VirtualBox,在Windows主机上装Ubuntu的虚拟机 视频教程在这: Virtualbox虚拟机安装,Ubuntu iso镜像下载_哔哩哔哩_bilibili 一、Ubuntu iso 镜像下载 我们是要在Windows主机上装Ubuntu的虚拟机,下载下Ubuntu iso 镜像。下…

react中如何避免父子组件同时渲染(memo的使用)

1.需求说明 react的渲染机制是父子组件同时渲染,不管子组件是否有变化只要父组件重新渲染了子组件就跟着重新渲染。为了避免不必要的消耗,我们可以使用memo钩子函数 2.使用memo前展示 import { memo,useState } from "react"function Son()…

【03】Java虚拟机是如何加载Java类的

从class文件到内存中的类,按先后顺序需要经过加载、链接以及初始化三个步骤 一、加载 加载就是查找字节流,并且据此创建类的过程。 除了启动类加载器(所有类加载器的祖师爷,由C实现,没有对应的Java对象)之外…

uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级

uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级 在开发MES系统的过程中,涉及到了平板端APP的开发,既然是移动端的应用,那么肯定需要APP版本的自动更新功能。 查阅相关资料后,在uniapp的…

安全哈希算法:SHA算法

🎯 主题简介 SHA(Secure Hash Algorithm)是比MD5更安全的哈希算法。通过案例形式了解SHA算法的原理、实现方法及注意细节。无论你是Python爱好者还是JavaScript高手,这篇内容都将为你提供一个深入了解SHA算法的机会。 &#x1f…