참고 1. 스프링-핵심-원리-고급편, 김영한
동시성 문제
여러 쓰레드가 동시에 같은 인스턴스의 필드 값을 변경하면서 발생하는 문제
동시성 문제가 발생하는 상황
- 지역 변수에서는 발생하지 않음. (지역 변수는 쓰레드마다 각각 다른 메모리 영역이 할당)
- 인스턴스의 필드, static 같은 공용 필드에 접근할 때 발생
- 주로 싱글톤에서 자주 발생
쓰레드 로컬, Thread Local
해당하는 쓰레드만 접근할 수 있는 특별한 저장소이다. 만약, "A" 쓰레드와 "B" 쓰레드가 있다면, A와 B 각각의 전용 저장소가 만들어 진다. 이후, A와 B가 데이터를 변경할 경우, 쓰레드 로컬이 각각의 전용 저장소에 연결해준다. 이를 통해 동시성 문제를 해결할 수 있다.
예시
동시성 문제가 발생하는 변수를 ThreadLocal로 감싸준다.
//동시성 문제가 발생하는 변수
private String store;
//ThreadLocal로 동시성 문제 개선
private ThreadLocal<String> store = new ThreadLocal<>();
함수
- 값 저장: ThreadLocal.set(value)
- 값 조회: ThreadLocal.get()
- 값 삭제: ThreadLocal.remove()
주의사항
쓰레드가 ThreadLocal을 모두 사용하고 나면, 반드시 ThreadLocal.remove()로 ThreadLocal에 저장된 값을 제거해야 한다.
- 왜 제거해야 할까?
- 쓰레드의 생성에는 많은 비용이 발생하기 때문에 WAS(톰캣)은 쓰레드를 미리 생성하고 쓰레드 풀에 보관한다. 사용자의 요청에 따라 쓰레드를 꺼내서 사용하고, 다시 쓰레드 풀에 반납한다.
- 이때, 쓰레드 풀의 1번 쓰레드를 첫 사용자의 요청에 사용되면, 이 쓰레드의 전용 ThreadLocal 저장소가 할당된다.
- 이후, 첫 사용자의 요청-응답 과정이 끝나면, 쓰레드는 쓰레드 풀에 반납된다. 즉, 쓰레드는 삭제가 되지 않으며, 전용 ThreadLocal 저장소 또한 유지가 된다.
- 이때, 두 번째 사용자의 요청이 들어오면 반납된 1번 쓰레드가 재사용될 수 있으며, 해당 ThreadLocal 저장소도 그대로 불러온다. 첫 사용자의 요청-응답 이후 ThreadLocal을 제거하지 않았다면, 데이터가 남아있게 된다.
- 꼭, 쓰레드의 반납 과정에서 ThreadLocal도 반드시 제거해주자
'스프링' 카테고리의 다른 글
[Spring] 디자인 패턴 - 전략 패턴 (0) | 2024.04.09 |
---|---|
[Spring] 디자인 패턴 - 템플릿 메서드 패턴 (0) | 2024.04.08 |
[Spring]IoC(Inversion of Control)와 DI (0) | 2024.03.28 |
[Spring] 객체 지향 설계 SOLID 개념과 적용 예시 (0) | 2024.03.25 |
스프링 - WebSocket (0) | 2024.03.07 |