【问题标题】:Spring: Singleton/session scopes and concurrencySpring:单例/会话范围和并发
【发布时间】:2010-12-17 06:38:57
【问题描述】:

Spring bean 的单例/会话范围是否要求必须同步对其所有字段的访问?通过“同步”关键字或使用包“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);
    }
}

【问题讨论】:

    标签: java spring concurrency scope


    【解决方案1】:

    基本上,对于启动会话的每个用户,都会创建一个新的ShoppingCart,并将其范围限定为每个用户的会话。

    你的类是线程安全的。初始化

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

    是线程安全的初始化和

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

    【讨论】:

    • 如果有人调用 getItems() 并开始对其进行迭代,而同时另一个线程执行 addItem(),您将抛出 ConcurrentModificationException。请参阅java.sun.com/javase/6/docs/api/java/util/ArrayList.html,了解需要与 ArrayList 同步线程安全的注意事项。
    • 该类不是线程安全的,因为“items”集合没有安全发布; items.add() 不提供任何保证其效果对线程可见而不是当前线程并且它不是原子的。
    • 嗯,我的印象是,类也是SessionScoped,并且只能由 Spring 容器中的单个参与者执行,这将确保类的线程安全?跨度>
    • 我认为如果使用 CopyOnWriteArrayList 会更安全
    【解决方案2】:

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

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

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

    再次强调,保护自己的最佳方法是尽量让 bean 保持无状态。如果你有一个需要状态的 bean,你应该考虑使用 prototype 范围,它每次都从容器中检索一个新的 bean 实例。

    【讨论】:

      【解决方案3】:

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

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

      您可能想查看此讨论中的 cmets 以了解更多信息: http://wheelersoftware.com/articles/spring-session-scoped-beans.html

      【讨论】:

        猜你喜欢
        • 2015-02-02
        • 2011-10-16
        • 1970-01-01
        • 1970-01-01
        • 2015-04-08
        • 2012-10-31
        • 1970-01-01
        • 2011-04-09
        • 1970-01-01
        相关资源
        最近更新 更多