2009-11-17 51 views
8

Spring bean的singleton/session作用域是否需要對其所有字段的訪問權限進行同步?通過「synchronized」關鍵字或使用「java.util.concurrent」包中的某些類說。Spring:Singleton/session作用域和併發性

舉例來說,這段代碼是不是線程安全的? (複製/ here pased):

@Component 
@SessionScoped 
public class ShoppingCart { 
    private List<Product> items = new ArrayList<Product>(); 

    public List<Product> getAllItems() { 
     return items; 
    } 

    public void addItem(Product item) { 
     items.add(item); 
    } 
} 

回答

21

當您使用從Spring容器singleton範圍,你指出,從容器獲取bean的所有線程將使用同樣的例子。因此,在這種情況下,如果項目的狀態列表在線程之間共享和可修改,則必須將訪問權限同步到列表中,以保護您的應用程序免受ConcurrentModificationException的影響。

但是,Spring的通常做法是使用無狀態對象來構建應用程序,這些對象的狀態不會在應用程序的整個生命週期中發生變化。

對於session作用域,您可能不太可能看到併發問題,因爲bean只能由當前登錄的用戶訪問。但是,有可能(至少在網絡上)在同一個會話中有多個請求進入,在這種情況下,您需要採取與bean是單例一樣的預防措施。

再一次保護自己的最佳方式是儘可能讓bean保持無狀態。如果你有一個需要狀態的bean,你應該考慮使用prototype作用域,它每次從容器中檢索一個新的bean實例。

-4

基本上是:啓動新ShoppingCart將被創建和範圍的每個用戶即會話的會話的每個用戶。

你的課是線程安全的。初始化

private List<Product> items = new ArrayList<Product>(); 

是線程安全的初始化和

addItem(Product item)是一個原子操作,並且也因此線程安全的。

+0

如果有人調用getItems()並開始迭代它,而同時另一個線程執行addItem(),則會導致ConcurrentModificationException異常。請參閱http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html以獲取關於需要使用ArrayList同步線程安全性的說明。 – 2009-11-17 02:27:00

+0

該類不是線程安全的,因爲'items'集合未被安全地發佈; items.add()不提供任何保證,它的效果對於線程來說比當前可見並且不是原子的。 – 2009-11-17 05:29:07

+0

嗯我的印象是這個類也是'SessionScoped',只能由Spring容器中的一個actor來執行,這樣可以確保類的線程安全嗎? – 2009-11-17 12:42:53