Возможна ли синхронизация в HttpSession?

ОБНОВЛЕНИЕ: Решение сразу после вопроса.

Вопрос:

Обычно синхронизация представляет собой сериализацию параллельных запросов внутри JVM, например.

private static final Object LOCK = new Object();

public void doSomething() {
  ...
  synchronized(LOCK) {
    ...
  }
  ...
}

При рассмотрении веб-приложений некоторая синхронизация в области «JVM global» может стать узким местом в производительности, и синхронизация только в пределах пользовательской HttpSessionбудет иметь больше смысла.

Возможен ли следующий код? Я сомневаюсь, что синхронизация на объекте сеанса — хорошая идея, но было бы интересно услышать ваши мысли.

HttpSession session = getHttpServletRequest().getSession();
synchronized (session) {
  ...
}

Ключевой вопрос:
Гарантируется ли, что объект сеанса является одним и тем же экземпляромдля всех потоков, обрабатывающих запросы от одного и того же пользователя?

Обобщенный ответ/решение:

Кажется, что сам объект сеанса не всегда один и тот же, поскольку он зависит от реализации контейнера сервлета (Tomcat, Glassfish, ...) и getSession() метод может возвращать только экземпляр оболочки.

Поэтому рекомендуется использовать пользовательскую переменную, хранящуюся в сеансе, в качестве объекта блокировки.

Вот мое предложение по коду, отзывы приветствуются:

где-то в вспомогательном классе, например.MyHelper:

private static final Object LOCK = new Object();

public static Object getSessionLock(HttpServletRequest request, String lockName) {
    if (lockName == null) lockName = "SESSION_LOCK";
    Object result = request.getSession().getAttribute(lockName);
    if (result == null) {
        // only if there is no session-lock object in the session we apply the global lock
        synchronized (LOCK) {
            // as it can be that another thread has updated the session-lock object in the meantime, we have to read it again from the session and create it only if it is not there yet!
            result = request.getSession().getAttribute(lockName);
            if (result == null) {
                result = new Object();
                request.getSession().setAttribute(lockName, result);
            }
        }
    }
    return result;
}

и затем вы можете его использовать:

Object sessionLock = MyHelper.getSessionLock(getRequest(), null);
synchronized (sessionLock) {
  ...
}

Есть комментарии по этому решению?

30
задан basZero 8 July 2015 в 08:12
поделиться