스터디/Spring

[SPRING 고급] 동시성 문제와 ThreadLocal 사용

혜유우 2024. 12. 17. 01:38
1. Thread-A는 userA를 nameStore에 저장했다.
2. Thread-B는 userB를 nameStore에 저장했다
3. Thread-A는 userB를 nameStore에서 조회했다.
4. Thread-B는 userB를 nameStore에서 조회했다.

 

📍동시성 문제

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

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

이런 동시성 문제는 여러 쓰레드가 같은 인스턴스의 필드에 접근해야 하기 때문에 트래픽이 적은 상황에서는 확률상 잘 나타나지 않고, 트래픽이 점점 많아질수록 자주 발생한다.

특히 스프링 빈처럼 싱글톤 객체의 필드를 변경하며 사용할때 이러한 동시성 문제를 조심해야 한다.

 

 ✓ 이런 동시성 문제는 지역변수에서는 발생하지 않는다. 지역변수는 쓰레드마다 각각 다른 메모리 영역이 할당된다.

동시성 문제가 발생하는 곳은 같은 인스턴스의 필드(주로 싱글톤에서 자주 발생) 또는 static 같은 공용 필드에 접근할 때 발생한다.

동시성 문제는 값을 읽기만 하면 발생하지 않는다. 어디선가 값을 변경하기 때문에 발생한다.

 

📍Thread Local

쓰레드 로컬을 사용하면 각 쓰레드마다 별도의 내부 저장소를 제공한다. 따라서 같은 인스턴스의 쓰레드 로컬 필드에 접근해도 문제 없다.

 

-일반적인 변수 필드: 여러 쓰레드가 같은 인스턴스의 필드에 접근하면 처음 쓰레드가 보관한 데이터가 사라질 수 있다.

 

ThreadLocal 사용법

-값 저장: ThreadLocal.set()

-값 조회: ThreadLocal.get()

-값 제거: ThreadLocal.remove()

🌟해당 쓰레드가 쓰레드 로컬을 모두 사용하고 나면 ThreadLocal.remove()를 호출해서 쓰레드 로컬에 저장된 값을 제거해주어야 한다. 

 

✔️ 주의사항

쓰레드 로컬의 값을 사용 후 제거하지 않고 그냥 두면 WAS(톰캣)처럼 쓰레드풀을 사용하는 경우에 심각한 문제가 발생할 수 있다

사용자B가 사용자A의 데이터를 확인하게 되는 심각한 문제가 발생할 수 있다

이런 문제를 예방하려면 사용자A의 요청이 끝날 때 쓰레드 로컬의 값을 ThreadLocal.remove()를 통해서 꼭 제거해야 한다. 🌟