동시성 문제란 무엇일까?
전역 변수에 대한 수정이 여러 쓰레드에서 일어날 경우 값에 대한 변경이나 조회가 예측할 수 없는 방향으로 흘러가는 것을 말한다.
스프링 빈은 기본적으로 싱글톤으로 등록이 된다.
여러 쓰레드에서 하나의 빈에 대해 동시에 접근할 경우에도 동시성 문제가 발생한다.
예를 보자.
Thread A에서 어떠한 로직으로 nameStore라는 전역 변수에 userA라는 이름을 저장한다.
이후 바로 Thread B에서 같은 로직으로 nameStore라는 전역 변수에 바로 접근해 userB라는 이름을 저장한다.
이 경우 각 쓰레드가 nameStore라는 전역 변수를 조회하게 되면 어떤 값이 조회될까?
당연히 userB라고 조회가 될 것이다.
Thread A는 userA를 예상했지만 userB는 예상하지 못한 값이다.
이게 사용자에 대한 개인정보라고 생각하면 문제가 심각해진다.
따라서 개발자에게 동시성 문제는 반드시 해결하고 넘어가야 하는 문제 중에 하나이다.
그러면 동시성 문제는 어떻게 해결할 수 있을까?
먼저, 동시성 문제는 지역 변수에서는 발생하지 않는다.
지역 변수는 쓰레드마다 각각 다른 메모리 영역이 할당되기 때문에 서로 변경해 침범할 일이 없는 것이다.
그러면 전역 변수도 지역 변수처럼 각각 다른 메모리 영역을 할당해주면 되지 않을까?
전역 변수에게 각각 다른 메모리 영역을 할당해줄 수는 없지만 전역 변수가 존재하는 쓰레드 별로 각각 다른 메모리 영역을 할당해주면 된다.
이를 가능하게 만들어주는 기능이 Java의 ThreadLocal이다.
ThreadLocal이란?
쓰레드 로컬은 해당 쓰레드만 접근할 수 있는 특별한 저장소를 말한다.
쓰레드 로컬을 사용하면 각 쓰레드마다 별도의 내부 저장소를 제공한다.
따라서 같은 인스턴스의 로컬 필드에 접근해도 문제가 발생하지 않는다.
ThreadLocal의 사용법
쓰레드 로컬은 java.lang.ThreadLocal 클래스를 사용한다.
쓰레드 로컬도 객체형태이기 때문에 set과 get을 써서 사용한다.
ThreadLocal<String> name = new ThreadLocal<>();
// 값 저장
name.set("이름");
// 값 조회
name.get();
// 값 제거
name.remove();
유의할 점이 한가지 있다.
코인 락커를 썼을 때도 다 사용하면 락커를 전부 비우고 반납해주는 것과 동일하다.
쓰레드를 다 썼을 때는 반드시 remove를 해 싹 비워서 쓰레드 풀에 돌려주자.
'Language > Java' 카테고리의 다른 글
OCP 원칙이란? (0) | 2024.06.25 |
---|---|
Java 필수 - 멀티쓰레드와 동기화 (feat. Atomic, Synchronized, Volatile) (0) | 2023.07.03 |
Java 기본 - Wrapper Class 래퍼 클래스 (0) | 2023.06.30 |
Java 기본 - 접근자 (0) | 2023.06.30 |
Java 기본 - 오버라이딩 오버로딩 (0) | 2023.06.29 |