Spring MVC 中的 Controller 是线程安全的吗?

Java后端技术

共 1733字,需浏览 4分钟

 ·

2022-05-25 09:23

往期热门文章:

1、Gitee 倒下了???

2、再见付费的 TeamViewer,这款国产轻量级远程控制软件是绝佳的替代品!

3、Mybatis-Plus官方发布分库分表神器,一个依赖轻松搞定!

4、Java 中的 BigDecimal,80% 的人竟然都用错了。。。

5、从5秒优化到1秒,系统飞起来了...

经常有面试题问到 Spring MVC 中的 Controller 是线程安全的吗?
在回答这个问题之前我们需要先了解一下,什么是线程安全?
下面这个图是来解释一下什么是多线程,红色的是 CPU 计算,蓝色的是 IO 操作,横坐标是时间,纵坐标是线程,那么我们可以发现,多线程是通过时间片的轮转切换上下文运行的,换句话说,就是同一时刻会有多个线程“同时运行”,这就是多线程。
引用:极客时间《Java 并发编程实战》
那么线程安全是什么呢?通俗点解释,当多个线程访问某个方法时,不会受其他线程影响,不管你通过怎样的方式调用返回结果都是我们期望的结果。写一个非常简单的例子来看一下什么是线程不安全
import java.util.Random;

public class ThreadTest {
    private int count;

    @SneakyThrows
    public int incCount() {
        Thread.sleep(new Random().nextInt(500));
        return count++;
    }

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        for (int i = 0; i < 100; i++) {
            new Thread(() -> System.out.println(threadTest.incCount())).start();
        }
    }
}
非常简单的例子,我们可以理解成是页面的阅读数,100 个人并发访问,最终返回页面的访问总数,结果出现了重复的 12(其他重复省略),最终是 90,那么是不是我们期望的是 99 才对?这就是线程不安全。
0
1
2
3
4
5
6
8
7
9
10
11
13
12
12
14
15
……
90
我们如何快速的解决这个问题呢?
添加 synchronized 关键字,synchronized 是同步的意思,表示无论你有多少线程,必须同步等待其他线程结束以后才能访问这个方法,问题是解决了,但是你运行程序的时候会发现,打印非常慢。
@SneakyThrows
public synchronized int incCount() {
    Thread.sleep(new Random().nextInt(500));
    return count++;
}
到这里线程安全说的差不多了,那我们还是回到 Spring MVC 的 Controller。是不是现在你已经明白了,Controller 它一定是线程不安全的。首先 Controller 是一个单例,其次每一次请求也是一个线程,那么如果在 Controller 中有变量的话一定会导致数据不准确。
那么如何解决呢?
首先尽量不要在 Controller 里面定义变量,如果不得不。那么
如果是通用的变量计算逻辑,使用 synchronized 等同步机制,如果是各自的计算逻辑直接放在 ThreadLocal 里面,保持线程独有的变量,这样既不影响性能,也保持数据准确。
往期热门文章:

1、我用Java几分钟处理完30亿个数据...
2、炸了!Java多线程批量操作,居然有人不做事务控制
3、巨坑,常见的 update 语句很容易造成Bug
4、完爆90%的数据库性能毛病!
5、Spring Boot性能太差,教你几招轻松搞定
6、Fastjson 2 来了,性能继续提升,还能再战十年
7、笑死!程序员延寿指南开源了
8、用 Dubbo 传输文件?被老板一顿揍!
9、45 个 Git 经典操作场景,专治不会合代码!
10、@Transactional 注解失效的3种原因及解决办法

浏览 23
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报