当前位置: 首页 > news >正文

线程安全问题及解决

1.前言

当我们使用多个线程访问同一资源时(可以是同一变量,同一文件,同一条记录),若多个线程只要只读操作,则不会发生线程安全问题;如果多个线程既有可读又有可写操作时,将可能导致线程安全问题.

2.提出问题

例 : 三个人对银行账户存储的100块存款进行取钱,如果该账户还有存款,就可以取.该问题可能发生线程安全问题吗?

3.继承Thread类的方式进行模拟 : 

public class ThreadTest {public static void main(String[] args) {MulterThread t1 = new MulterThread("线程-1");MulterThread t2 = new MulterThread("线程-2");MulterThread t3 = new MulterThread("线程-3");t1.start();t2.start();t3.start();}
}
class MulterThread extends Thread {static int change = 100;public MulterThread() {super();}public MulterThread(String name) {super(name);}@Overridepublic void run() {while(true) {if (change > 0) {System.out.println(Thread.currentThread().getName() + "\t\t" + change);change--;} else {break;}}}
}控制台 : 
//显然有问题,100的时候被取的两次
线程-2		100
线程-1		100
线程-2		99
线程-1		98
线程-2		97
线程-1		96
线程-2		95
线程-1		94
线程-1		92
线程-2		93
略

注 : 

  • 为什么change变量要声明为static : 如果不声明为static,那么new了三个MulterThread对象,就会有300块的存款,与抢占同一资源的场景不符.
  • 为什么会出现两次100呢 : 很显然,每次运行结果不一样,按该次运行结果举例.当线程2调用run()方法进入输出语句的时候,执行到下一句change--还需要一段时间,而此时线程1也调用了run(),并也执行到了输出语句,此时change--语句并未执行,所以二者都打印的是100.

3.实现Runnable接口的方法进行模拟

public class RunnableTest {public static void main(String[] args) {A a = new A();Thread t1 = new Thread(a);Thread t2 = new Thread(a);Thread t3 = new Thread(a);t1.start();t2.start();t3.start();}}
class A implements Runnable{int change = 100;@Overridepublic void run() {while (true) {if (change > 0) {System.out.println(Thread.currentThread().getName() + "\t\t" + change);change--;} else {break;}}}
}控制台 : 
Thread-1		100
Thread-1		99
Thread-1		98
Thread-0		100
Thread-1		97
Thread-0		96
Thread-2		100
Thread-0		94
Thread-1		95
Thread-1		91
略

注 : 

  • 为什么change变量不用static修饰 : 只调用一次new创建了A的一个对象,并作为同一个实参传入到Thread类中.因为只new了一次,所以change只有一份.
  • 为什么会出现三次100 : 与上同.

4.解决方案

必须满足一个线程在操作change时,其他线程必须等待,直到该线程操作完成后,其他线程才可以进来操作change.

5.方式1 : 同步代码块

(1). 格式

synchronized(同步监视器){

    //需要被同步的代码

}

(2). 利用锁来解决继承Thread类带来的线程安全问题.

@Overridepublic void run() {while(true) {synchronized (MulterThread.class){if (change > 0) {System.out.println(Thread.currentThread().getName() + "\t\t" + change);change--;} else {break;}}}}

(3). 利用锁来解决实现接口带来的线程安全问题 : 

@Overridepublic void run() {while (true) {synchronized (this){if (change > 0) {System.out.println(Thread.currentThread().getName() + "\t\t" + change);change--;} else {break;}}}}

说明 : 

  • 需要被同步的代码,即为操作共享数据的代码.
  • 共享数据 : 即多个线程可以操作的数据 : 如该处的change.
  • 需要被同步的代码,在被synchronized包裹后,就使得一个线程操作共享数据时,其他线程需等待.
  • 同步监视器(锁) : 哪个线程获得了锁,哪个线程就可以执行被同步的代码.
  • 锁可以由任何对象充当,但必须多个线程共用同一个同步监视器.(即该监视器必须唯一).
  • 继承Thread类 : 锁---->类名.class
  • 实现接口 : 锁------>this

相关文章:

线程安全问题及解决

1.前言 当我们使用多个线程访问同一资源时(可以是同一变量,同一文件,同一条记录),若多个线程只要只读操作,则不会发生线程安全问题;如果多个线程既有可读又有可写操作时,将可能导致线程安全问题. 2.提出问题 例 : 三个…...

Excel·VBA数组平均分组问题

看到一个帖子《excel吧-数据分组问题》,对一组数据分成4组,使每组的和值相近 上一篇文章《ExcelVBA数组分组问题》,解决了这个帖子问题的第1步,即获取所有数组分组形式的问题 接下来要获取分组和值最相近的一组,只需计…...

高防服务器、高防IP、高防CDN的工作原理是什么

高防IP高防CDN我们先科普一下是什么是高防。“高防”,顾名思义,就犹如网络上加了类似像盾牌一样很高的防御,主要是指IDC领域的IDC机房或者线路有防御DDOS能力。 高防服务器主要是比普通服务器多了防御服务,一般都是在机房出口架设…...

【Flask开发实战】安装mysql数据库与配置连接

1、安装mysql 通过yum方式安装MySQL服务器: sudo yum install mysql-server 在安装过程中,系统可能会要求确认安装。按下Y键并按回车键继续。 安装完成后,MySQL服务器应已自动启动。可以使用以下命令查看和启动MySQL服务: sudo…...

Java项目:79 springboot海滨体育馆管理系统的设计与实现

作者主页:舒克日记 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 体育馆管理系统主要实现了管理员功能模块和学生功能模块两大部分 管理员功能模块: 管理员登录后可对系统进行全面管理操作,包…...

17.注释和关键字

文章目录 一、 注释二、关键字class关键字 我们之前写的HelloWorld案例写的比较简单,但随着课程渐渐深入,当我们写一些比较难的代码时,在刚开始写完时,你知道这段代码是什么意思,但是等过了几天,再次看这段…...

Mac上配置host

要在Mac上配置host,可以按照以下步骤进行操作: 打开终端:输入以下命令并按下回车键,以获取管理员权限: sudo nano /etc/hosts 这将打开一个文本编辑器,用于编辑hosts文件。 输入你想要配置的host记录。…...

JAVA------基础篇

java基础 1.JDK JDK :java development kit JRE:java runtime environment JDK包含JRE java跨平台:因为java程序运行依赖虚拟机,虚拟机需要有对应操作系统的版本,而jre中有虚拟机。 当你想要在Linux系统下运行,则需要…...

Python人工智能:气象数据可视化的新工具

Python是功能强大、免费、开源,实现面向对象的编程语言,在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能,这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…...

springMVC实现细节

DispatcherServlet、拦截器、处理器详解(通俗易懂)_处理器和拦截器的区别-CSDN博客...

ubuntu16 apt安装程序锁死解决

目录 1.使用apt install安装程序有时会爆出dpkg/lock类故障 2.使用lsof命令查看占用锁的进程 3.使用kill -9命令删除占用进程 4.删除锁 5. 配置生效 1.使用apt install安装程序有时会爆出dpkg/lock类故障 E: Could not get lock /var/lib/dpkg/lock - open (11: Resource …...

计算机网络——26通用转发和SDN

通用转发和SDN 网络层功能: 转发: 对于从某个端口 到来的分组转发到合适的 输出端口路由: 决定分组从源端 到目标端的路径 网络层 传统路由器的功能 每个路由器(Per Route)的控制平面 (传统) 每个路由器上都有实…...

Modbus TCP协议介绍(ModbusTCP)

文章目录 理解Modbus TCP协议(Understanding Modbus TCP Protocol)简介(Introduction to Modbus TCP)历史背景(Historical Context)关键特性(Key Features) Modbus TCP协议结构&…...

【Java核心能力】一篇文章了解 ZooKeeper 底层运行原理

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送! 在我后台回复 「资料」 可领取编程高频电子书! 在我后台回复「面试」可领取硬核面试笔记! 文章导读地址…...

P2123皇后游戏

P2123皇后游戏 参考题解 #include <iostream> #include <algorithm> using namespace std;int T; int n; long long res;struct Person {int a,b,d; }p[20005];bool person_cmp(const Person& x,const Person& y) {if(x.d y.d){if(x.d < 0)return x.a …...

git之目前的主流版本

官方文档 简介 我们都知道&#xff0c;在开发过程中&#xff0c;版本控制是至关重要的。Git作为目前最为流行的版本控制系统&#xff0c;已经成为了开发者们的标配。出于好奇&#xff0c;本人对git目前主流几大版本&#xff08;GitLab、GitHub、Gitee 和 GitCode&#xff09;…...

PyQT5学习--新建窗体模板

目录 1 Dialog 2 Main Window 3 Widget Dialog 模板&#xff0c;基于 QDialog 类的窗体&#xff0c;具有一般对话框的特性&#xff0c;如可以模态显示、具有返回值等。 Main Window 模板&#xff0c;基于 QMainWindow 类的窗体&#xff0c;具有主窗口的特性&#xff0c;窗口…...

企业产品网络安全建设日志0328

文章目录 Actuator再次暴露域名上线基线检查初见效果WAF更新遇波折301跳转推进中 Actuator再次暴露 为了验证挖f的拦截效果&#xff0c;自己随手拼了个Actuator&#xff0c;结果可以访问到公司的actuator。。 据称是某网关更换新组件后未做防御&#xff0c;已要求全部做防御&a…...

QT(C++)-error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”

1、项目场景&#xff1a; 在VS中采用QT&#xff08;C&#xff09;调试时&#xff0c;出现error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”错误 2、解决方案&#xff1a; 在“解决方案资源管理器”中选中出现此类BUG的项目&#xff0c;右键-…...

【 MyBatis 】| 关于多表联查返回 List 集合只查到一条的 BUG

目录 一. &#x1f981; 写在前面二. &#x1f981; 探索过程2.1 开端 —— 开始写 bug2.2 发展 —— bug 完成2.3 高潮 —— bug探究2.4 结局 —— 效果展示 三. &#x1f981; 写在最后 一. &#x1f981; 写在前面 今天又是 BUG 气满满的一天&#xff0c;一个 xxxMapper.xm…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...

聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇

根据 QYResearch 发布的市场报告显示&#xff0c;全球市场规模预计在 2031 年达到 9848 万美元&#xff0c;2025 - 2031 年期间年复合增长率&#xff08;CAGR&#xff09;为 3.7%。在竞争格局上&#xff0c;市场集中度较高&#xff0c;2024 年全球前十强厂商占据约 74.0% 的市场…...

stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)

这是系统中断服务程序的默认处理汇编函数&#xff0c;如果我们没有定义实现某个中断函数&#xff0c;那么当stm32产生了该中断时&#xff0c;就会默认跑这里来了&#xff0c;所以我们打开了什么中断&#xff0c;一定要记得实现对应的系统中断函数&#xff0c;否则会进来一直循环…...