惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
J
Java Code Geeks
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
Docker
腾讯CDC
The GitHub Blog
The GitHub Blog
大猫的无限游戏
大猫的无限游戏
Microsoft Security Blog
Microsoft Security Blog
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
博客园 - 司徒正美
T
The Blog of Author Tim Ferriss
Vercel News
Vercel News
P
Proofpoint News Feed
雷峰网
雷峰网
博客园_首页
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
V
V2EX
F
Fortinet All Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
MyScale Blog
MyScale Blog
S
SegmentFault 最新的问题

博客园 - gogoy

LangChain的Deep Agents学习 Java 开发中 一篇文章讲清楚VO,BO,PO,DO,DTO的区别 云原生:Mesh化架构模式(sidecar模式)、容器vsPod Serverless 介绍 图解直接映射(Direct mapped)、全相联(Fully-associative)和组相联(Set-associative)cache缓存基本原理 为什么大语言模型推理要分成 Prefill 和 Decode? 【台大机器学习系列1】机器学习2021 人工智能交互中的角色与提示词:System、User与Assistant 台大李宏毅 2025 AI Agent 新课来了!(即李宏毅机器学习2025) 一文搞懂Passkey(转) RISC-V、x86、ARM技术对比解析 各种函数依赖及规范化解决 SSE协议与HTTP协议 操作日志 “二清”详解:支付产品必须知道的“清结算规矩” 金融通识:国内支付清算体系CNAPS2 Mockito教程(单测mock) zookeeper TCP相关经典 Java常见的超时及设计
Spring单例Bean并发安全问题分析和解决
gogoy · 2025-10-31 · via 博客园 - gogoy

问题来源

1. Spring Bean默认是单例

Java

@Service("submitTestReportService")  // 默认单例
public class SubmitTestReportServiceImpl extends AbstractTestReportService

2. 抽象类中有共享的可变实例变量

Java

public abstract class AbstractTestReportService {
    

3. 并发访问导致数据混乱

  • 线程A调用 reportV1(reqIssueId=70162961)
  • 线程B调用 reportV1(reqIssueId=67510805)
  • 由于共享实例变量,线程A可能读取到线程B设置的数据

问题表现

Java

// 用户报告的问题:
// 当reqIssueId=70162961时,SQL查询结果为空
// 但this.testReportSummaryOriginal中的数据却来自reqIssueId=67510805

解决方案对比

❌ 错误方案:同步锁

Java

public synchronized Map<String, String> reportV1(...) {
    

✅ 推荐方案:线程安全的上下文对象

Java

// 1. 创建不可变的上下文对象
protected static class TestReportContext {
    public final ReqInfo reqInfo;
    public final List<Issue subIssues;
    

通用解决方案

1. 上下文对象模式(Context Pattern)

  • 将所有相关数据封装到一个不可变对象中
  • 通过方法参数传递,而不是实例变量存储
  • 每个请求都有独立的上下文实例

2. 设计原则

  • 无状态设计:Service层应该是无状态的
  • 局部变量优先:尽量使用方法参数和局部变量
  • 不可变对象:上下文对象的字段使用final修饰

3. 适用场景

  • Spring单例Bean中需要处理复杂业务流程
  • 多个方法间需要共享数据
  • 有继承关系的抽象类和具体实现类

最佳实践总结

Java

// ✅ 好的设计
public class Service {
    public Result process(Request request) {
        Context context = buildContext(request);  

这种上下文对象模式是处理Spring单例Bean并发问题的标准解决方案,既保证了线程安全,又维持了良好的性能和代码可读性。

其它: