강의 메모 - ThreadLocal - 1,2 #
개요 #
- 자바에서 스레드는 오직 자신만이 접근해서 읽고 쓸수 있는 로컬 변수 저장소를 제공하는데 이를 ThreadLocal 이라고 한다
- 각 스레드는 고유한 ThreadLocal 객체를 속성으로 가지고 있으며 ThreadLocal 은 스레드 간 격리되어 있다
- 스레드는 ThreadLocal 에 저장된 값을 특정한 위치나 시점에 상관없이 어디에서나 전역변수처럼 접근해서 사용할 수 있다. 변수 값을 전달하지 않아도 된다
- 모든 스레드가 공통적으로 처리해야 하는 기능이나 객체를 제어해야 하는 상황에서 스레드마다 다른 값을 적용해야 하는 경우 사용한다 (인증 주체 보관, 트랜잭션 전파, 로그 추적기 등)
- Thread 마다 ThreadLocal을 가지고있다.
- ThreadLocal은 각자 ThreadLocalMap이라는 객체를 가지고있어서 값을 가진다.
ThreadLocal API #
- void set(T value)
- 스레드 로컬에 값을 저장한다
- T get()
- 스레드 로컬에 저장된 값을 가져온다
- void remove()
- 스레드 로컬에 저장된 값을 삭제한다
- withInitial(Supplier<? extends S> supplier)
- 스레드 로컬을 생성하면서 특정 값으로 초기화한다
Thread & ThreadLocal #
- 스레드는 ThreadLocal 에 있는 ThreadLocalMap 객체를 자신의 threadLocals 속성에 저장한다.
- 스레드 생성 시 threadLocals 기본값은 null 이며 ThreadLocal 에 값을 저장할 때 ThreadLocalMap 이 생성되고 threadLocals 과 연결된다
- 스레드가 전역적으로 값을 참조할 수 있는 원리는 스레드가 ThreadLocal 의 ThreadLocalMap 에 접근해서 여기에 저장된 값을 바로 꺼내어 쓸수 있기 때문이다
- ThreadLocalMap 은 항상 새롭게 생성되어 스레드 스택에 저장되기 때문에 근본적으로 스레드간 데이터 공유가 될 수 없고 따라서 동시성 문제가 발생하지 않는다
- threadLocal은 1개인거고 여기 내부에서 ThreadLocalMap이 여러개 생기는것
주의사항 #
- ThreadLocal 에 저장된 값은 스레드마다 독립적으로 저장되기 때문에 저장된 데이터를 삭제하지 않아도 메모리를 점유하는 것 외에 문제가 되지는 않는다.
- 그러나 스레드 풀을 사용해서 스레드를 운용한다면 반드시 ThreadLocal 에 저장된 값을 삭제해 주어야 한다
- 스레드풀은 스레드를 재사용하기 때문에 현재 스레드가 이전의 스레드를 재사용한 것이라면 이전의 스레드에서 삭제하지 않았던 데이터를 참조할 수 있기 때문에 문제가 될 수 있다
ThreadLocal 작동원리 #
- ThreadLocal 은 Thread 와 ThreadLocalMap 을 연결하여 스레드 전용 저장소를 구현하고 있는데 이것이 가능한 이유는 바로 Thread.currentThread() 를 참조할 수 있기 때문이다
- Thread.currentThread() 는 현재 실행중인 스레드의 객체를 참조하는 것으로서 CPU 는 오직 하나의 스레드만 할당받아 처리하기 때문에 ThreadLocal 에서 Thread.currentThread() 를 참조하면 지금 실행 중인 스레드의 로컬 변수를 저장하거나 참조할 수 있게 된다
- ThreadLocal 에서 현재 스레드를 참조할 수 있는 방법이 없다면 값을 저장하거나 요청하는 스레드를 식별할 수 없기 때문에 Thread.currentThread() 는 ThreadLocal 의 중요한 데이터 식별 기준이 된다
데이터 저장 #
데이터 조회 #
InheritableThreadLocal #
- InheritableThreadLocal은 ThreadLocal의 확장 버전으로서 부모 스레드로부터 자식 스레드로 값을 전달하고 싶을 경우 InheritableThreadLocal을 사용할 수 있다
- 값의 상속:
- 부모 스레드가 InheritableThreadLocal 변수에 값을 설정하면, 해당 부모 스레드로부터 생성된 자식 스레드들은 부모의 값을 상속받게 된다
- 독립성
- 자식 스레드가 상속받은 값을 변경하더라도 부모 스레드의 값에는 영향을 주지 않는다