Весна: объемы синглтона / сессии и параллелизм - PullRequest
9 голосов
/ 17 ноября 2009

Требует ли, чтобы одноэлементные / сеансовые области бинов Spring требовали синхронизации доступа ко всем его полям? Произнесите ключевое слово «synchronized» или используйте некоторые классы из пакета «java.util.concurrent».

Например, этот код не является потокобезопасным? (скопировать / перенести с здесь ):

@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 ]

24 голосов
/ 17 ноября 2009

Когда вы используете singleton scope из контейнера Spring, вы указываете, что все потоки, которые извлекают bean-компонент из контейнера, будут использовать один и тот же экземпляр. Таким образом, в этом случае, когда список состояний элемента совместно используется и может изменяться между потоками, вам нужно будет синхронизировать доступ к списку, чтобы защитить приложение от ConcurrentModificationException.

Однако обычная практика в Spring - создавать приложение с объектами без состояния, состояние которых не будет меняться в течение всего жизненного цикла приложения.

В случае области действия session вероятность возникновения проблемы параллелизма может быть меньше, поскольку компонент будет доступен только вошедшему в систему пользователю. Тем не менее, возможно (по крайней мере, в Интернете) иметь несколько запросов на один и тот же сеанс, и в этом случае вам нужно будет принять те же меры предосторожности, как если бы компонент был одноэлементным.

Опять же, лучший способ защитить себя - постараться сохранить свой бин как можно без гражданства. Если у вас есть компонент, для которого требуется состояние, вам следует рассмотреть возможность использования области действия prototype, которая каждый раз получает новый экземпляр компонента из контейнера.

0 голосов
/ 17 ноября 2009

В основном для каждого пользователя, который инициирует сеанс, будет создан новый ShoppingCart и область действия этого сеанса для этого пользователя.

Ваш класс потокобезопасен. Инициализация

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

- это потокобезопасная инициализация, а

addItem(Product item) является атомарной операцией и, следовательно, поточно-ориентированным.

0 голосов
/ 17 ноября 2009

Только пользователь для этого сеанса может получить доступ к этому классу, но ArrayList не является потокобезопасным, как видно из этого обсуждения: http://forums.sun.com/thread.jspa?threadID=5355402

Вы должны убедиться, что ваш класс полностью поточно-ориентирован, так как SessionScoped просто гарантирует, что он используется только каждым сеансом, поэтому один сеанс не может получить к нему доступ.

Вы можете посмотреть комментарии в этой дискуссии для получения дополнительной информации: http://wheelersoftware.com/articles/spring-session-scoped-beans.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...