개발/Java

ThreadLocal

Debin 2022. 6. 27.
반응형

ThreadLocal

쓰레드 로컬은 해당 쓰레드만 접근할 수 있는 특별한 저장소다.

쓰레드 로컬을 사용하면 각 쓰레드마다 별도의 내부 저장소를 제공한다.

따라서 같은 인스턴스의 쓰레드 로컬 필드에 접근해도 문제 없다.

 

여러 쓰레드가 같은 인스턴스의 멤버 변수에 접근하면 처음 쓰레드가 보관한 데이터가 사라질 수 있는데,

이런 경우 쓰레드 로컬을 사용하면 데이터를 안정적으로 접근하고 사용할 수 있다.

쓰레드 로컬 사용

thread-A userA 라는 값을 저장하면 쓰레드 로컬은 thread-A 전용 보관소에 데이터를 안전하게 보관한다.
thread-B userB 라는 값을 저장하면 쓰레드 로컬은 thread-B 전용 보관소에 데이터를 안전하게 보관한다.

 

자바는 언어차원에서 쓰레드 로컬을 지원하기 위한 java.lang.ThreadLocal 클래스를 제공한다.

 

쓰레드 로컬 덕분에 쓰레드 마다 각각 별도의 데이터 저장소를 가지게 되므로, 실습에서 동시성 문제를 해결했다.

 

ThreadLocal은 내부에 ThreadLocalMap을 가지고 있는데 이는 항상 새롭게 생성되어 스레드 스택에 저장되기 때문에 근본적으로 스레드간 데이터 공유가 될 수 없고 따라서 동시성 문제가 발생하지 않는다.

 

ThreadLocal 사용법

ThreadLocal.set();    //값 저장
ThreadLocal.get();    //값 조회
ThreadLocal.remove(); //값 제거

 

중요한 부분이 있다.
해당 쓰레드가 쓰레드 로컬을 모두 사용하고 나면 ThreadLocal.remove() 를 호출해서 쓰레드 로컬에 저장된 값을 제거해주어야 한다.
만약 쓰레드 로컬에 저장된 값을 제거하지 않으면 무슨일이 발생할까?

  1. 스프링의 톰캣 같은 경우에는 사용자의 HTTP 요청이 들어오면 쓰레드 풀에서 쓰레드 1개를 할당한다.
  2. 이걸 thread-A라고 부르겠다. 그럼 thread-A의 쓰레드 로컬에는 사용자 A의 정보가 저장된다.
  3. 그리고 정보를 활용해, 로직을 마치면 HTTP 응답이 끝난다. 
  4. 그러면 thread-A를 쓰레드 풀에 반환한다. 여기서 만약 쓰레드 로컬에 저장된 값을 제거하지 않으면 어떻게 될까?
  5. 다음번에 thread-A를 할당하면, 이전 사용자에 대한 정보가 들어있으므로 큰 문제가 발생할 것이다.

따라서 무조건 사용자의 요청이 끝날 때 ThreadLocal.remove()를 통해서 꼭 제거해야 한다.

 

이상으로 포스팅을 마칩니다. 감사합니다.

 

참고자료

스프링 고급편 https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8/dashboard

 

스프링 핵심 원리 - 고급편 - 인프런 | 강의

스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

반응형

댓글