You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
스레드 로컬은 해당 스레드만 접근할 수 있는 특별한 저장소를 말한다. 쉽게 이야기해서 물건 보관 창구를 떠올리면 된다. 여러 사람이 같은 물건 보관 창구를 사용하더라도 창구 직원은 사용자를 인식해서 사용자별로 확실하게 물건을 구분해준다.
사용자 A, 사용자 B 모두 창구 직원을 통해서 물건을 보관하고 꺼내지만 창구 직원이 사용자에 따라 보관한 물건을 구분해주는 것이다.
일반적인 변수 필드
여러 스레드가 같은 인스턴스의 필드에 접근하면 처음 스레드가 보관한 데이터가 사라질 수 있다.
thread-A가 userA라는 값을 저장하고
thread-B가 userB라는 값을 저장하면 직전에 thread-A가 저장한 userA값은 사라진다.
이 문제를 해결해주는 것은
스레드 로컬
스레드 로컬을 사용하면 각 스레드마다 별도의 내부 저장소를 제공한다. 따라서 같은 인스턴스의 스레드 로컬 필드에 접근해도 문제가 없다.
threadA가 userA 라는 값을 저장하면 스레드 로컬은 threadA전용보관소에 데이터를 안전하게 보관한다.
threadB가 userB이라는 값을 저장하면 스레드 로컬은 thread-B전용 보관소에 데이터를 안전하게 보관한다.
스레드 로컬을 통해서 데이터를 조회할때도 threadA가 조회하면 스레드 로컬은 threadA 전용보관소에서 userA데이터를 반환해준다. 물론 thread-B가 조회하면 thread B 전용 보관소에서 userB 데이터를 반환해준다.
동시에 들어와도 구분해서 처리해준다.
자바는 언어 차원에서 스레드 로컬을 지원하기 위한 java.lang.ThreadLocal클래스를 제공한다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
ThreadLocal 소개
스레드 로컬은 해당 스레드만 접근할 수 있는 특별한 저장소를 말한다. 쉽게 이야기해서 물건 보관 창구를 떠올리면 된다. 여러 사람이 같은 물건 보관 창구를 사용하더라도 창구 직원은 사용자를 인식해서 사용자별로 확실하게 물건을 구분해준다.
사용자 A, 사용자 B 모두 창구 직원을 통해서 물건을 보관하고 꺼내지만 창구 직원이 사용자에 따라 보관한 물건을 구분해주는 것이다.
일반적인 변수 필드
thread-A가 userA라는 값을 저장하고
thread-B가 userB라는 값을 저장하면 직전에 thread-A가 저장한 userA값은 사라진다.
이 문제를 해결해주는 것은
스레드 로컬
스레드 로컬을 사용하면 각 스레드마다 별도의 내부 저장소를 제공한다. 따라서 같은 인스턴스의 스레드 로컬 필드에 접근해도 문제가 없다.


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

스레드 로컬을 통해서 데이터를 조회할때도 threadA가 조회하면 스레드 로컬은 threadA 전용보관소에서 userA데이터를 반환해준다. 물론 thread-B가 조회하면 thread B 전용 보관소에서 userB 데이터를 반환해준다.
동시에 들어와도 구분해서 처리해준다.
자바는 언어 차원에서 스레드 로컬을 지원하기 위한
java.lang.ThreadLocal클래스를 제공한다.ThreadLocal - 예제코드
ThreadLocal 사용법
ThreadLocal.set(xxx)ThreadLocal.get()ThreadLocal.remove()실행결과
동시성 문제 발생하게끔 실행
스레드 로컬 동기화 - 개발
FieldLogTrace에서 발생했던 동시성 문제를ThreadLocal로 해결해보자TraceId traceIdHolder필드를 스레드 로컬을 사용하도록ThreadLocal<TraceId> traceIdHolder로 변경하면 된다.필드 대신에 스레드 로컬을 사용해서 데이터를 동기화하는
ThreadLocalLogTrace를 새로 만든다.traceIdHolder가 필드에서ThreadLocal로 변경되었다. 따라서 값을 저장할때는 set() 을 사용하고 값을 조회할때는 get()을 사용한다.ThreadLocal.remove()
추가로 스레드 로컬을 모두 사용하고 나면 꼭 ThreadLocal.remove()를 호출해서 스레드 로컬에 저장된 값을 제거해줘야한다.
쉽게 이야기 해서 다음의 마지막 로그를 출력하고 나면 스레드 로컬의 값을 제거해야한다.
여기서는
releaseTraceId()를 통해 level1이 점점 낮아져서 2→ 1→ 0이 되면 로그를 처음 호출한 부분으로 돌아온 것이다. 따라서 이 경우 연관된 로그 출력이 끝난것이다. 이제 더이상 TraceId 값을 추적하지 않아도 된다.그래서
traceId.isFirstLevel()(level==0)인 경우ThreadLocal.remove()를 호출해서 스레드 로컬에 저장된 값을 제거해준다.실행결과
스레드 로컬 동기화 - 적용
LogTraceConfig - 수정
동시요청
스레드 로컬 - 주의사항
스레드 로컬의 값을 사용 후 제거하지 않고 그냥 두면 WAS처럼 스레드 풀을 사용하는 경우에 심각한 문제가 발생할 수 있다.
사용자 A 저장 요청
사용자 A 저장 요청 종료
사용자 B 조회 요청
결과적으로 사용자 B는 사용자 A의 데이터를 확인하게 되는 심각한 문제가 발생하게 된다.
이런 문제를 예방하려면 사용자 A의 요청이 끝날때 스레드 로컬의 값을
ThradLoca.remove()를 통해서 꼭 제거해야 한다.All reactions