如何避免Bean的线程安全问题

通常情况下Bean是基于单例模式创建的对象,不存在线性安全问题。但是如果Bean对象中存在公有的变量被多线程调用将会导致变量数据错乱。

复制代码
@Service
public class UserService {
    private int count = 0;
    public void add() {
        count++; // 多线程下计数错误
    }
}

有以下4种解决方案:

1、设计成无状态的Bean:Bean对象中不存放可变的实例变量,通过内部方法修改变量值。

复制代码
// 安全写法:无状态 Bean
@Service
public class UserService {
    // 没有任何可修改的成员变量

    public int add(int num) {
        // 局部变量,线程安全
        int count = 0;
        count = count + num;
        return count;
    }
}

2、改用原型作用域

@Scope(""),每次getBean都会创建一个新的实例

3、bean中用线程安全的数据结构

CuncurrentHashMap代替HashMap,让每个Bean都加上锁。同样也可以手动上synchronized锁。

4、用ThreadLocal:

每个线程维护自己的变量副本互补干扰。

复制代码
@Service
public class UserService {
    // 线程独立存储
    private ThreadLocal<Integer> countLocal = ThreadLocal.withInitial(() -> 0);

    public void add() {
        int count = countLocal.get();
        countLocal.set(count + 1);
    }

    // 用完必须 remove,防止内存泄漏
    public void clear() {
        countLocal.remove();
    }
}

注意每个线程都需要通过remove()方法清理线程。防止未清理情况下复用线程导致数据错乱。

企业开发中通过全局配置AOP拦截方法进行清理。

复制代码
@Aspect
@Component
public class ThreadLocalCleanAspect {

    // 拦截所有 @Service、@Controller 方法
    @Pointcut("execution(* com.xxx..service.*.*(..)) || execution(* com.xxx..controller.*.*(..))")
    public void servicePointcut() {}

    // 【最终通知】无论方法正常/异常,都执行清理
    @After("servicePointcut()")
    public void cleanThreadLocal() {
        ThreadContext.clear();
    }
}
相关推荐
Fnetlink11 分钟前
Fnet 云网安 261023
运维·开发语言·网络·人工智能·安全·web安全·php
泡茶喝茶写代码6 分钟前
A股量化策略回测实战:从行情数据到绩效评估(第 13 篇):放量突破策略
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口
文丑颜不良啊10 分钟前
LeetCode626~650题目解析
java·leetcode
ESDWAN12 分钟前
SD-WAN 主备切换为什么仍会断网?从检测、切换到会话恢复分析
运维·开发语言·网络·php
jimy115 分钟前
lvalue、xvalue、prvalue(二):引用是哪一类?
开发语言·c++·1024程序员节
cxyxixiy18 分钟前
数智码力:数据核对不用人工比对,Python 快速完成多表格差异校验
开发语言·python·学习
一个风轻云淡22 分钟前
从 int $0x80 到 iret:用 gdb 把 getpid 走一遍
linux·c语言·开发语言·汇编
杜 硕26 分钟前
从零开始的C++生活——第三讲
开发语言·c++·生活
tianbin91136 分钟前
批处理与微调辅助场景:Claude 中转并发、链路缓存与压测对比
java·开发语言·缓存
frjc44 分钟前
Spring AI 里 ChatClient 和 ChatModel 有什么区别?什么时候该用哪个?
java·开发语言·spring·ai