Spring:Singleton / session范围和并发

时间:2009-11-17 00:21:53

标签: java spring concurrency scope

Spring bean的singleton / session范围是否要求必须同步对其所有字段的访问?通过“synchronized”关键字或使用包“java.util.concurrent”中的某些类来说。

例如,这段代码不是线程安全的吗? (复制/来自here):

@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);
    }
}

3 个答案:

答案 0 :(得分:24)

当您使用Spring容器中的singleton作用域时,表明从容器中检索bean的所有线程都将使用相同的实例。因此,在这种情况下,项目的状态列表在线程之间共享和修改,您必须同步对列表的访问以保护您的应用程序免受ConcurrentModificationException的攻击。

但是,Spring的通常做法是使用无状态对象构建应用程序,这些对象没有在应用程序的整个生命周期中都会发生变化的状态。

对于session范围,您可能不太可能看到并发问题,因为bean只能由当前登录的用户访问。但是,有可能(至少在网络上)在同一个会话中有多个请求,在这种情况下,您需要采取相同的预防措施,就像bean是单例一样。

同样,保护自己的最佳方法是尽量保持豆子无国籍。如果你有一个需要状态的bean,你应该考虑使用prototype范围,每次从容器中检索一个新的bean实例。

答案 1 :(得分:0)

只有该会话的用户才能访问此类,但ArrayList不是线程安全的,如本讨论中所示:http://forums.sun.com/thread.jspa?threadID=5355402

您需要确保您的类完全是线程安全的,因为SessionScoped将确保它仅由每个会话使用,因此一个会话无法访问它。

您可能需要查看此讨论中的评论以获取更多信息: http://wheelersoftware.com/articles/spring-session-scoped-beans.html

答案 2 :(得分:-4)

基本上,对于发起会话的每个用户,将为该用户创建新的ShoppingCart并确定该会话的范围。

您的课程是线程安全的。初始化

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

是一个线程安全的初始化和

addItem(Product item)是一个原子操作,因此也是线程安全的。