Spring Security에서 Context Holder를 ThreadLocal로 구현했다.
이는 각 쓰레드들이 각자의 context holder를 가지고 있다는 것이며
그렇기 때문에 무수한 HTTP 요청으로 쓰레드가 여러마리 생기더라도 ContextHolder에서 꺼낸 인증정보들이 꼬이지 않는 것이다.
final class ThreadLocalSecurityContextHolderStrategy implements
SecurityContextHolderStrategy {
private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<>();
public SecurityContext getContext() {
SecurityContext ctx = contextHolder.get();
if (ctx == null) {
ctx = createEmptyContext();
contextHolder.set(ctx);
}
return ctx;
}
public void setContext(SecurityContext context) {
Assert.notNull(context, "Only non-null SecurityContext instances are permitted");
contextHolder.set(context);
}
public SecurityContext createEmptyContext() {
return new SecurityContextImpl();
}
// 쓰레드풀을 사용하는 환경에서는 이 부분이 매우 중요하다.
// 이유는 아래에...
public void clearContext() {
contextHolder.remove();
}
}
ThreadLocal 을 사용할 때 주의점
쓰레드 풀에서 뛰쳐나오는 쓰레드 생성비용이 커서 미리 만들어 둔 쓰레드들이기 때문에 재사용이 이루어진다.
쓰레드풀을 관리하는 톰캣(Tomcat)아저씨를 우리가 사용하는 경우,
톰캣아저씨가 사용하는 쓰레드가 재사용 될 때 이전의 ThreadLocal 변수를 참조하지 않도록 Clear 해주는 작업이 필요하다.
참고로 Spring에는 톰캣이 내장되어 있다. (즉 Spring 사용시에도 주의해야한다.)
톰캣(WAS) 아저씨의 쓰레드풀 관련 글
Thread-Safe
자바에서는 동기화 블록 또는 동기화 메소드를 사용하여 해결한다.
동기화 키워드(Synchronized)를 사용하면 현재 데이터를 사용하고 있는 쓰레드만 자원에 접근하고 다른 쓰레드들은 wait 상태에 빠진다.