Spring

ThreadLocal이란?

do_hyuk 2024. 4. 28. 12:51

Thread Local이란?

Java에서 지원하는 Thread safe한 기술로 멀티 스레드 환경에서 각각의 스레드에게 별도의 저장공간을 할당하여

별도의 상태를 갖을 수 있게끔 도와준다.

 

ThreadLocal이 필요한 이유

예를들어 Spring의 tomcat을 보면 매 요청마다 생성해놓은 Thread pool에서 Thread를 할당하여 유저의 요청을 처리하도록

되어있다. 여기서 문제가 발생하는데 Spring에서 bean을 등록하게 되면 해당 객체는 단 1개만 만들어져서 모든 Thread가

공유하여 사용하도록 되어있다. 이때 해당 인스턴스의 특정 필드를 모든 Thread가 공유하게 되는 것인데 여기서

Thread 동기화 문제가 발생하게 된다.

 

이해하기 쉽도록 그림을 통해 예시를 들어보도록 하겠다.

  • fieldService라는 싱글톤 인스턴스가 존재하고 해당 인스턴스에 nameStore이라는 필드가 있다고 가정하자
  • 먼저 thread-A 가 userA 값을 nameStore 에 보관한다

- 0.1초 이후에 thread-B 가 userB 의 값을 nameStore 에 보관한다.

   기존에 nameStore 에 보관되어 있던 userA 값은 제거되고 userB 값이 저장된다.

  • thread-A 의 호출이 끝나면서 nameStore 의 결과를 반환받는데, 이때 nameStore 는 앞의 2번에서 userB 의 값으로
    대체되었다. 따라서 기대했던 userA 의 값이 아니라 userB 의 값이 반환된다.
  • thread-B 의 호출이 끝나면서 nameStore 의 결과인 userB 를 반환받는다.

동시성 문제

결과적으로 Thread-A 입장에서는 저장한 데이터와 조회한 데이터가 다른 문제가 발생한다.

이처럼 여러 쓰레드가 동시에 같은 인스턴스의 필드 값을 변경하면서 발생하는 문제를 동시성 문제라 한다.

이런 동시성 문제는 여러 쓰레드가 같은 인스턴스의 필드에 접근해야 하기 때문에 트래픽이 적은 상황에서는 확률상 잘 나타나지 않고, 트래픽이 점점 많아질 수 록 자주 발생한다. 특히 스프링 빈 처럼 싱글톤 객체의 필드를 변경하며 사용할 때 이러한 동시성 문제를

조심해야 한다.

 

참고
이런 동시성 문제는 지역 변수에서는 발생하지 않는다. 지역 변수는 쓰레드마다 각각 다른 메모리 영역이 할당된다. 동시성 문제가 발생하는 곳은 같은 인스턴스의 필드(주로 싱글톤에서 자주 발생), 또는 static 같은 공용 필드에 접근할 때 발생한다. 동시성 문제는 값을 읽기만 하면 발생하지 않는다. 어디선가 값을 변경하기 때문에 발생한다.


ThreadLocal 사용시 주의점

ThreadLocal을 사용할 때 반드시 인지해야할 주의할 점이 있다.

앞서 이야기했듯이 우리가 사용하는 WAS(tomcat)은 Thread pool 기반으로 동작한다.

따라서 ThreadLocal을 사용할 때 사용 후에 비워주지 않는다면 해당 Thread를 부여받게 되는 다른 사용자가

기존에 세팅된 ThreadLocal의 데이터를 공유하게 될 수도 있다.
그렇기에, Thread 의 사용이 끝나는 시점에 Thread Pool에 반환을 하기 직전 반드시 ThreadLocal을 초기화시켜주는

작업을 해줘야 한다.

 

REF) ThreadLocal은 무엇일까