spring 中的 bean 是线程安全的吗?
Spring 不保证 bean 的线程安全。
默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题。如下面的例子
计数类
package constxiong.interview.threadsafe; /** * 计数类 * @author ConstXiong * @date 2019-07-16 14:35:40 */ public class Counter { private int count = 0; public void addAndPrint() { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(++count); } }
spring 配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="counter" class="constxiong.interview.threadsafe.Counter" /> </beans>
测试类
package constxiong.interview.threadsafe; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class CounterTest { public static void main(String[] args) { final ApplicationContext context = new ClassPathXmlApplicationContext("spring_safe.xml"); for (int i = 0; i < 10; i++) { new Thread(){ @Override public void run() { Counter counter = (Counter)context.getBean("counter"); for (int j = 0; j < 1000; j++) { counter.addAndPrint(); } } }.start(); } } }
打印结果开头和结尾
1 5 7 4 2 6 3 8 9 . . . 9818 9819 9820 9821 9822 9823 9824 9825
期望打印出的最大值应该是 10000
修改 spring 配置文件,把 bean 的作用域改为 prototype
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="counter" class="constxiong.interview.threadsafe.Counter" scope="prototype"/> </beans>
测试结果输出10个 1000
即每个线程都创建了一个 Counter 对象,线程内独自计数,不存在线程安全问题。但是不是我们想要的结果,打印出 10000。
所以 spring 管理的 bean 的线程安全跟 bean 的创建作用域和 bean 所在的使用环境是否存在竞态条件有关,spring 并不能保证 bean 的线程安全。
Atas ialah kandungan terperinci spring中的bean是线程安全的吗?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!