当前位置: 首页 > 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…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...