콘텐츠로 이동

2022 08 09

2022-08-09

ThreadLocal

  • 참고: https://madplay.github.io/post/java-threadlocal
  • 개요
    • 쓰레드 단위로 로컬 변수를 사용할 수 있음 => 마치 전역 변수처럼 여러 메서드에서 활용 가능
    • 큰 부작용이 발생할 수 있기에, 다른 쓰레드와 변수가 공유되지 않도록 주의할 것!
  • ThreadLocalMap
    • 외부에서 접근 가능한 메서드 X
    • 내부적으로 해시테이블 정보를 가짐
    • WeakReference 확장하여 ThreadLocal 객체를 Key로 사용하는 Entry 클래스
      public class ThreadLocal<T> {
          static class ThreadLocalMap {
              static class Entry extends WeakReference<ThreadLocal<T>> {
      
              }
          }
      }
      
  • Thread
    • Thread 클래스는 ThreadLocalMap 타입 멤버 필드로 가지고 있음
    • 특정 스레드의 정보를 ThreadLocal에서 직접 호출할 수 있도록 함
      public class Thread implements Runnable {
          ThreadLocal.ThreadLocalMap threadLocals = null;
      }
      
  • ThreadLocal
    • set: 쓰레드 로컬에 값 저장
    • get: 쓰레드 로컬에서 값 가져오기
      public void set(T value) {
          Thread t = Thread.currentThread();
          ThreadLocalMap map = getMap(t);
          if (map != null) {
              map.set(this, value);
          } else {
              createMap(t, value);
          }
      }
      
      public T get() {
          Thread t = Thread.currentThread();
          ThreadLocalMap map = getMap(t);
          if (map != null) {
              ThreadLocalMap.Entry e = map.getEntry(this);
              if (e != null) {
                  T result = (T) e.value;
                  return result;
              }
          }
          return setInitialValue();
      }
      
      ThreadLocalMap getMap(Thread t) {
          return t.threadLocals;    
      }
      
      void createMap(Thread t, T firstValue) {
          t.threadLocals = new ThreadLocalMap(this, firstValue);    
      }
      
  • 주의할 사안
    • ThreadPool에서는 쓰레드를 재사용하기 때문에, ThreadLocal 값을 제거해줘야함!
    • 제거 안해주면 재사용 된 쓰레드가 ThreadLocal 값을 부여잡고 있을 수 있음!
  • ThreadLocal의 활용
    • 클라이언트 요청에 대해서 각각의 스레드에서 처리할 때나, 쓰레드 독립적으로 처리해야하는 데이터와 같이 "인증 관련 처리"에서도 활용 가능
    • 대표적인 사용처는 Spring Security의 SecurityContext, SecurityContextHolder