系列十四、Spring如何处理线程安全问题

一、线程安全问题出现的原因

        Spring中出现线程安全的原因是,单实例bean中存在成员变量,并且有对这个bean进行读写的操作,因此出现了线程安全的问题。

二、案例代码

2.1、MySpringConfig

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/10/24 17:39
 * @Description:
 */
@Configuration
@ComponentScan(basePackages = "org.star")
public class MySpringConfig {

}

2.2、UserService

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/10/24 17:35
 * @Description: 演示单实例bean存在线程安全问题
 */
@Service
public class UserService {

    private String username;

    public String welcome(String name) {
        username = "welcome " + name;
        try {
            // 休眠100毫秒:模拟处理业务耗时100毫秒
            Thread.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return username;
    }

}

2.3、测试

public class Spring16MainApp {

    public static void main(String[] args) {
        existThreadSafe();
    }

    /**
     * 演示单实例bean存在线程安全问题
     */
    private static void existThreadSafe() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);
        // 线程一
        UserService userService = context.getBean(UserService.class);
        new Thread(() -> {
            System.out.println(userService.welcome("张三"));
        }).start();

        // 线程二
        UserService userService2 = context.getBean(UserService.class);
        new Thread(() -> {
            System.out.println(userService2.welcome("李四"));
        }).start();
    }

}

2.4、结果

实际结果跟预期结果不一致,出现了线程安全问题。

三、解决方式

3.1、将成员变量修改为局部变量

3.2、将bean改为多例的

3.3、将成员变量放到ThreadLocal中

3.4、加同步锁

你可能感兴趣的:(Spring全家桶面试系列,spring,java,mysql)