0

0

在Java里线程不安全的常见场景有哪些_Java并发问题说明

P粉602998670

P粉602998670

发布时间:2026-02-02 15:50:03

|

851人浏览过

|

来源于php中文网

原创

线程不安全问题主要表现为共享变量未加锁导致值覆盖、非线程安全集合并发修改异常、工具类复用引发状态错乱、局部变量逃逸破坏线程隔离,需用原子类、并发集合、ThreadLocal、不可变对象及正确同步机制防范。

在java里线程不安全的常见场景有哪些_java并发问题说明

共享变量未加锁直接读写

多个线程同时读写同一个 intString 或自定义对象字段,且没用 synchronizedvolatile 或原子类,就会出现值被覆盖、丢失更新。比如两个线程都执行 counter++(本质是读-改-写三步),很可能最终只加了 1 次而不是 2 次。

常见于计数器、状态标志、缓存计数等场景。注意:volatile 能保证可见性和禁止重排序,但不能保证复合操作的原子性——volatile int countcount++ 仍是线程不安全的。

  • AtomicInteger 替代普通 int 做计数
  • 临界区代码块必须用 synchronized(this) 或显式 ReentrantLock
  • 避免在 getter/setter 中直接暴露可变对象引用(如返回内部 ArrayList 实例)

非线程安全集合被并发修改

ArrayListHashMapHashSet 这些类本身不保证线程安全。多线程往里面 add()put(),轻则数据丢失,重则触发 ConcurrentModificationException,甚至死循环(JDK 7 中 HashMap 扩容时链表成环)。

不是所有“正在遍历中修改”才出错——即使只是多个线程纯写入,也存在结构不一致风险。

立即学习Java免费学习笔记(深入)”;

  • 优先用 CopyOnWriteArrayList(适合读多写少)、ConcurrentHashMap(高并发读写首选)
  • 避免用 Collections.synchronizedList(new ArrayList()) 后忘记对迭代操作额外加锁
  • ConcurrentHashMapsize()isEmpty() 返回近似值,不能用于条件判断逻辑

静态工具类或单例持有可变状态

看似“无状态”的工具类,如果内部缓存了 SimpleDateFormatRandom 或某个 StringBuilder 实例并复用,就极易出问题。例如 SimpleDateFormatparse()format() 方法不是线程安全的,共享一个实例会导致解析错乱、格式化结果异常。

LLaMA
LLaMA

Meta公司发布的下一代开源大型语言模型

下载

这种问题隐蔽性强,单元测试往往跑不出,压测或线上流量突增时才暴露。

  • 每次使用都新建 SimpleDateFormat(注意对象创建开销)
  • 改用 DateTimeFormatter(JDK 8+,不可变、线程安全)
  • 若必须复用,用 ThreadLocal 隔离实例
  • 检查所有 static 字段:是否无意中成了多线程共享的可变状态容器

错误地认为“局部变量天然线程安全”而忽略逃逸

局部变量本身确实在线程上,但一旦它引用的对象被发布到其他线程可见的作用域(比如作为参数传给另一个线程、放进共享队列、赋值给静态字段),那它的状态就不再受线程栈保护。

典型例子:在方法里 new 出一个 ArrayList,往里塞数据后 add 到全局 Queue;或者把局部 StringBuilder 传给异步回调函数——这些对象的内容可能正被多个线程同时修改。

  • 向共享结构传递对象前,考虑是否需要深拷贝或不可变封装(如 ImmutableList.copyOf(list)
  • 避免在 lambda 表达式或匿名内部类中直接捕获可变局部变量并跨线程使用
  • @NotThreadSafe@ThreadSafe 注解明确标注类的设计意图,辅助团队识别风险点

真正危险的不是“不知道要加锁”,而是“以为自己已经锁住了”,比如锁对象选错(用了局部变量当锁)、同步块范围太小、或误信某些 JDK 类的线程安全性(像 TreeMap 就不是线程安全的,哪怕 ConcurrentHashMap 是)。多线程调试没法靠单步,得靠设计时的明确边界和防御性编码习惯。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

523

2023.08.02

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

844

2023.07.31

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

437

2024.06.27

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

523

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

546

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

133

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

200

2025.08.29

AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

29

2026.02.02

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.1万人学习

C# 教程
C# 教程

共94课时 | 8.3万人学习

Java 教程
Java 教程

共578课时 | 55.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号