безопасное использование Threadlocal в Java - PullRequest
0 голосов
/ 27 ноября 2018

В настоящее время у меня есть веб-проект.Я сохраняю переменную типа sessionid в threadlocal в Перехватчике SpringMVC и удаляю ее в методе postHandle.Но мне интересно, безопасно это или нет.ех.если поток сохранил sessionid, то произошло переключение контекста процессора, в этом случае что-то еще возьмет этот поток и установит другой sessionid или удалит его в postHandle.Когда мы переключаемся обратно, sessionid изменился.Если это возможно, у нас есть другие решения?

@Interceptor
public class BusinessInterceptor extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
    Object handler) throws Exception {
    ThreadLocalUtil.contextThreadLocal.set(createSessionId());
    return true;
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
    Object handler, Exception ex)
    throws Exception {
    ThreadLocalUtil.contextThreadLocal.remove();
}
}

1 Ответ

0 голосов
/ 27 ноября 2018

Вас немного смущает значение Переключение контекста .Просто взглянув на Википедию, она определяется как:

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

Где сохранение состояния системы для одной задачи означает сохранение всех значений, к которым у потока есть доступ, который, конечно, включает в себя локальные потоки.Поэтому переключение контекста связано с разделением времени процессора, а не с разделением данных между потоками.(Ну, да, есть также переключение контекста, когда ОС переходит из пользовательский режим в режим ядра , но я думаю, что это не тот тип, который ОП думает в своем уме).

Кроме того, локальные потоки будут содержать различное значение в зависимости от потока, который имеет к нему доступ.Если мы посмотрим на определение ThreadLocal в Java:

Эти переменные отличаются от своих обычных аналогов тем, что каждый поток обращается к одному (с помощью его метода get или set) имеет собственную , независимо инициализированную копию переменной.

Итак, ответ таков: Нет, никакой другой поток не сможет прочитать значение этого локального потокапеременная , независимо от числа происходящих переключений контекста.


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

Вы должны знать, что в это время, когда у нас есть модели асинхронного / реактивного выполнения, HTTP / 2 и т. д., ваше предположение не оправдается, так как у вас будет более одного потокавыполнение данного запроса ... и из-за этого ваша локальная переменная потока будет либо неинициализирована, либо будет содержать совершенно неожиданное значение, когда любой другой поток попытается получить к ней доступ.И это принесет много головной боли.

Я бы порекомендовал вам найти другой способ передачи вашего идентификатора сессии , и я бы порекомендовал вам сделать это явно как параметр для последующих функций, которые могут в этом нуждаться.

...