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

 

 

修改 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 的線程安全。


原文鏈接
 


 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM