ThreadLocal
쓰래드 로컬을 알고있어야 하는 이유중 하나는 동시성 문제이다.
동시성 문제
동시성 문제?
첫호출작업이 끝나기도 전에 동시에 다발적으로 호출하게되면 로그가 분리되지않고 떡져서 출력된다.
즉 어떠한 작업을 수행하는 스레드의 트랜젝션이 보장이 되지 않는것이다.
이런 동시성 문제는 여러 쓰레드가 같은 인스턴스 필드에 접근해야 하기 때문에 트래픽이 적은 상황에서는 확율상 잘 나타나지않고 트래픽이 점점 많아질수록 자주 발생해야한다.
특히 스프링 빈처럼 싱글톤 객체의 필드를 변경하며 사용할때 이러한 동시성 문제를 조심해야한다java에서 지역변수에는 동시성문제가 발생하지 않다. 왜냐하면 스레드마다 각각 다른 메모리 영역이 할당한다.
동시성문제가 발생하는곳은 같은 인스턴스필드 (싱글톤 static)같은 공용 필드에 접근할때 발생한다. 동시성문제는 값을 읽을때 생기는것이 아닌 어디선가 값을 변경할때 발생한다.2022-03-18 14:01:50.203 INFO 8125 --- [nio-8080-exec-1] \
위 로그는 일반적으로 스프링에서 볼 수 있는 로그..
*[nio-8080-exec-1] 이 부분은 톰켓에 와스가 알려주는 스래드이름이다. 해당 스택을 실행하는 쓰래드 이름입니다.**
스프링을 작업하다보면 동시성문제를 직면하면 이 로그를 자세히보면 동시성 문제인지 체크할 수 있다.동시성문제가 생긴 이유들중 하나는 해당 스택의 인스턴스가 싱글톤이라면 하나의 인스턴스에 여러개의 쓰래드가 동시에 몰렸을것.
동시성 문제를 해결하기위해 ThreadLocal 사용
스레드 로컬은 해당 스레드만 접근할 수 있는 특별한 저장소를 말한다. 물건 보관 창구 같ㅣ 여러사람이 같은 물건 보관 창구를 사용하더라도
창구직원은 사용자를 인식해서 사용자별로 확실하게 물건을 구분해 준다.
- 일반적인 변수 필드
여러 쓰레드가 같은 인스턴스필드에 접근하면 처음쓰레드가 보관한 데이터가 사라질 수 있다.먼저 작업한 스레드가 후에 들어온 스레드가 값을 덮어씌우거나 하는경우. - 쓰래드 로컬
스레드 로컬을 사용하면 각 스레드마다 별도의 내부 저장소를 제공한다. 따라서 같은 인스턴스의 쓰레드 로컬 필드에 접근해도 문제가 없다.
스레드 로컬을 통해서 데이터를 조회할때도 스레드로컬 전용 보관소에서 구분해서 데이터를 문제해준다. java는 java.lang.ThreadLocal을 지원한다.
사용법
ex )
private ThreadLocal<String> 변수 = new ThreadLocal<>();
변수.get() //값을 가져올때
변수.set() //값을 저장할때
주의 사항
- 해당 스레드가 스레드 로컬을 모두 사용하고 나면 ThreadLocal.remove()를 호출해서 스레드로컬을 제거해 줘야한다.. 이때 리무브 하는 내용은 해당 스레드가 배정된 스레드 보관소만 제거해준다. 즉 1 스레드 2스레드 가 있을때 1만 지워질 수 도 있는것
스레드로컬의 값을 사용후 제거하지않고 was처럼 스레드 풀을 사용하는 경우 에 심각한문제가 생길 수 있다. 왜냐하면 어떠한 사용자가 배정받은 스레드를 다 쓰고 사용자가 나가면서 스레드가 반환이 되기때문에 해당사용자의 데이터가 스레드에 그대로 남아있을 수가 있기때문에 큰 문제를 야기시킨다.
- 요청이끝난다면 꼭 ThreadLocal.remove()를 호출해서 스레드로컬을 제거해 줘야한다.
'Springboot' 카테고리의 다른 글
java리플렉션 (0) | 2023.08.14 |
---|---|
탬플릿 메서드 패턴 (0) | 2023.08.14 |
Spring Data ElasticSearch NativeSearchQuery Paging 처리 (0) | 2022.12.07 |
JPA update시에 dto null 체크및 feild 유무 판단하는 util class (0) | 2022.10.28 |
JPA/지연로딩과 즉시로딩 개념과 권장 사용법 정리, 그리고 OneToOne의 지연로딩 (0) | 2022.10.21 |