java常见的几种并发安全问题及解决方案
项目场景:
并发的应用场景,在开发过程会经常遇到。
例如:服务应用启动后,需要简单统计接口的总访问量;实时更新订单状态,成交总额。
问题描述:
比如统计接口访问次数,如下的实现,在并发访问下,统计是不准确的 。
private int viewCount = 0;private void addViewCount(){viewCount++;}
比如A、B两个线程同时访问,各自从JVM主存中加载变量viewCount到线程内存里viewCount的值都是0,各自+1,更新会JVM主存的也是1。实际A、B执行完毕后,JVM的值应该是2才对。
解决方案:
并发问题解决,实际有2种方式:有锁、无锁。
有锁的就是关键字synchronized,以及可重入锁ReentrantLock。
无锁的,就是局部变量、不可变对象、CAS原子类、ThreadLocal,共四种。
具体解决方案分析:
一.无锁方式
1.局部变量
/*** 局部变量,多线程更新count的时候,各自在线程内存中创建i变量。*/public void localParam(){int count = 0;/*本次处理业务,统计*/count++;System.out.println(count);}
2.不可变对象
车辆位置实时更新,传统的setY,setY,在并发过程会出差错。定义一个final localtion类,并且构造函数直接初始化x,y。/*** 车辆位置经纬度值*/
public final class Location {private final double x;private final double y;public Location(double x, double y) {this.x = x;this.y = y;}
}
同时定义一个traker类,来存储多个车辆的位置信息,更新的时候直接用新的location位置类,去update ConcurrentHashMap。
/*** 不可变类,实现并发更新安全* 通过每次更新位置,直接初始化一个全新的location,然后set到车辆位置map中*/
public class CarLocationTracker {/*** 车辆编码对应车辆位置信息map* ConcurrentHashMap,是利用CAS+synchronized来保证并发安全*/private Map<String, Location> locationMap = new ConcurrentHashMap<>();/*** 更新车辆位置** @param carCode 车辆编码* @param newLocation 车辆新位置*/public void updateLocation(String carCode, Location newLocation) {locationMap.put(carCode, newLocation);}/*** 获取车辆位置** @param carCode 车辆斌吗* @return*/public Location getLocation(String carCode) {return locationMap.get(carCode);}
}
3.ThreadLocal
ThreadLocal 变量,线程局部变量.同一个ThreadLocal所包含的对象,在不同线程中有不同的副本。 private static final ThreadLocal threadCount= new ThreadLocal();/*** ThreadLocal 变量,线程局部变量*/public void threadLocalParam(){Integer count = (Integer) threadCount.get();/*本次处理业务,统计*/count++;System.out.println(count);}
4.CAS原子类
CAS 机制,三个基本操作:内存地址V,旧的预期值A,要修改的新值B,只有当内存地址V所对应的值与旧的预期值A相等,才会将内存地址V对应的值更新为B。 private AtomicInteger counter = new AtomicInteger(0);/*** cas 原子类,是个乐观锁,并发性能很高。通过compare and swap比较并置换的原子性设计,read 从jvm主存中读取旧值oldV,* 更新的时候,先比较oldV与主存中的v是否相等,相等就把newV更新替换v;如果不相等,继续while循环,从主存读取'新的'旧值oldV。** 底层是c++实现,保证三个步骤执行在硬件级别,是原子性,要么三个一起执行成功,又不继续循环直到成功。*/public void atomicAdd(){//比如接口访问总次数统计System.out.println(counter.incrementAndGet());}
二.有锁方式
1. 关键字synchronized
//访问统计private int viewCount = 0;public synchronized void syncAdd(){addViewCount();}private void addViewCount(){viewCount++;}
2. 可重入锁ReentrantLock
//悲观锁private ReentrantLock lock = new ReentrantLock();//访问统计private int viewCount = 0;private void addViewCount(){viewCount++;}/*** 通过执行方法前,加锁;执行完毕主动释放锁保证int++ 并发安全*/public void lockAdd(){lock.lock();try {addViewCount();} finally {lock.unlock();}}
相关文章:

java常见的几种并发安全问题及解决方案
项目场景: 并发的应用场景,在开发过程会经常遇到。 例如:服务应用启动后,需要简单统计接口的总访问量;实时更新订单状态,成交总额。 问题描述: 比如统计接口访问次数,如下的实现&a…...

介绍一下安装时情况 kubernetes 集群
1.安装命令执行完毕 最开始告诉我们应用的版本 v1.29.14前置检测下载镜像写入证书因为当前我们所有的 kubernetes 集群的组件之间的联通 都是基于HTTPS协议实现的 补充知识点:BS架构,即Browser/Server(浏览器/服务器)架构模式&a…...

Dify部署踩坑指南(Windows+Mac)
组件说明 Dify踩坑及解决方案 ⚠️ 除了修改镜像版本,nginx端口不要直接修改docker-compose.yaml !!!!!!! 1、更换镜像版本 这个文件是由.env自动生成的,在.env配置 …...

安科瑞新能源充电桩解决方案:驱动绿色未来,赋能智慧能源
安科瑞顾强 引言 在“双碳”目标与新能源汽车产业高速发展的双重驱动下,充电基础设施正成为能源转型的核心环节。安科瑞电气股份有限公司凭借在电力监控与能效管理领域20余年的技术积淀,推出新一代新能源充电桩解决方案,以智能化、高兼容性…...
深入剖析Java代理模式:静态代理与动态代理的实战应用
代理模式是Java开发中最重要的设计模式之一,广泛应用于性能监控、访问控制、日志记录等场景。本文将带你全面掌握代理模式的实现原理,并通过3种不同的代码实现方式,彻底理解这一核心设计模式的应用技巧。 一、代理模式的核心价值 代理模式(Proxy Pattern)通过创建代理对…...
JVM与性能调优详解
以下是关于 JVM与性能调优 的详细解析,结合理论、实践及常见问题,分多个维度展开: 一、JVM性能调优的核心目标 性能调优的核心目标是通过优化内存管理、垃圾回收(GC)策略和线程管理,实现以下平衡ÿ…...
【嵌入式通信协议】串口的详细介绍
以下是对嵌入式STM单片机通信串口的详细介绍 一、STM32串口通信基础 STM32的串口模块称为USART(Universal Synchronous/Asynchronous Receiver/Transmitter),支持同步和异步通信;而UART(Universal Asynchronous Receiver/Transmitter)仅支持异步通信。STM32F103C8T6包含…...

乐鑫打造全球首款 PSA Certified Level 2 RISC-V 芯片
乐鑫科技 (688018.SH) 荣幸宣布 ESP32-C6 于 2025 年 2 月 20 日获得 PSA Certified Level 2 认证。这一重要突破使 ESP32-C6 成为全球首款基于 RISC-V 架构获此认证的芯片,体现了乐鑫致力于为全球客户提供安全可靠、性能卓越的物联网解决方案的坚定承诺。 PSA 安全…...

Go学习笔记:基础语法3
1. 常量 Go语言中的常量使用关键字const定义,用于存储不会改变的数据,常量是在编译时被创建的,即使定义在函数内部也是如此,并且只能是布尔型、数字型(整数型、浮点型和复数)和字符串型。 由于编译时的限…...

虚拟卡 WildCard (野卡) 保姆级开卡教程
本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 本篇教程为 WildCard 的介绍以及开卡教学,要了解不同平台(Grok、Talkatone 等)的订阅方式请移步《订阅教程》分类 当我们想要充值国外平台会员时,一般都需要使…...
机试准备第10天
首先学习二分搜索法。使用二分查找需要先排序。第一题是查找,现学现卖。 //二分查找 #include <stdio.h> #include <vector> #include <algorithm> using namespace std; int main(){int n;scanf("%d", &n);vector<int> a(n…...
Apache ECharts介绍(基于JavaScript开发的开源数据可视化库,用于创建交互式图表)
文章目录 Apache ECharts 介绍功能概览多种图表类型- **基础类型**:折线图、柱状图、饼图、散点图。- **高级类型**:雷达图、热力图、桑基图、K线图。- **地理可视化**:支持地图(如中国、世界)和地理坐标系。- **3D支持…...

最新版本TOMCAT+IntelliJ IDEA+MAVEN项目创建(JAVAWEB)
前期所需: 1.apache-tomcat-10.1.18-windows-x64(tomcat 10.1.8版本或者差不多新的版本都可以) 2.IntelliJ idea 24年版本 或更高版本 3.已经配置好MAVEN了(一定先配置MAVEN再搞TOMCAT会事半功倍很多) 如果有没配置…...
Linux - 进程通信
一、管道 管道是一种进程间通信(IPC)机制,用于在进程之间传递数据。它的本质是操作系统内核维护的一个内存缓冲区,配合文件描述符进行数据的读写。尽管管道的核心是内存缓冲区,但操作系统通过对管道的实现,…...

使用 Arduino 的 WiFi 控制机器人
使用 Arduino 的 WiFi 控制机器人 这次我们将使用 Arduino 和 Blynk 应用程序制作一个 Wi-Fi 控制的机器人。这款基于 Arduino 的机器人可以使用任何支持 Wi-Fi 的 Android 智能手机进行无线控制。 为了演示 Wi-Fi 控制机器人,我们使用了一个名为“Blynk”的 Andr…...

网络安全等级保护2.0 vs GDPR vs NIST 2.0:全方位对比解析
在网络安全日益重要的今天,各国纷纷出台相关政策法规,以加强信息安全保护。本文将对比我国网络安全等级保护2.0、欧盟的GDPR以及美国的NIST 2.0,分析它们各自的特点及差异。 网络安全等级保护2.0 网络安全等级保护2.0是我国信息安全领域的一…...
verb words
纠正correct remedy 修正modify 协商 confer 磋商/谈判 negotiate 通知notice notify *宣布announce 声明declare 宣告 declare *颁布 promulgate /introduce 协调coordinate 评估evaluate assess 撤离evacuate *规定stipulate 参与participate, 涉及refer…...

unity console日志双击响应事件扩展
1 对于项目中一些比较长的日志,比如前后端交互协议具体数据等,这些日志内容可能会比较长,在unity控制面板上查看不是十分方便,我们可以对双击事件进行扩展,将日志保存到一个文本中,然后用系统默认的文本查看…...
维度建模维度表技术基础解析(以电商场景为例)
维度建模维度表技术基础解析(以电商场景为例) 维度表是维度建模的核心组成部分,其设计直接影响数据仓库的查询效率、分析灵活性和业务价值。本文将从维度表的定义、结构、设计方法及典型技术要点展开,结合电商场景案例,深入解析其技术基础。 1. 维度表的定义与作用 定义…...

Leetcode 264-丑数/LCR 168/剑指 Offer 49
题目描述 我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。 示例: 说明: 1 是丑数。 n 不超过1690。 题解 动态规划法 根据题意,每个丑数都可以由其他较小的丑数通过乘以 2 或 3 或 5 得到…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...