[JAVA] ThreadLocal

joyful·2021년 9월 5일
0

Java/Spring

목록 보기
25/28
post-custom-banner

1. 개요

  • 스레드 단위로 로컬 변수를 제공하는 클래스

  • get 또는 set 메서드를 통해 접근하는 각 스레드가 고유하고 독립적으로 초기화 된 변수의 복사본을 갖는다는 점에서 일반 변수와 다름

    • 일반 변수의 수명은 특정 코드 블록 범위 내에서만 유효

    • stack 영역에 변수를 선언하는 것에 대한 단점 해소 가능

      영역설명
      Heap일반적으로 모든 thread에서 접근 가능
      stackthread 하나당 생성되는 메모리 영역이므로 thread간 접근 불가능
      • 변수 공유 : 파라미터로 받아 사용
      • 변수 사용 : 다른 곳에서 사용하려면 리턴값으로 제공
  • ThreadLocal 인스턴스는 일반적으로 상태를 스레드와 연결하려는 클래스의 private static 필드
    → 다른 스레드에서 해당 값을 접근하거나 변경하지 않는 것을 보장
    ex) 사용자 ID 또는 트랜잭션 ID

  • 내부적으로 thread 정보를 key로 하여 값을 저장해두는 Map 구조를 가지고 있음

✅ 동작 방식

  • 동일한 코드 실행 시, 스레드1에서 실행할 경우 관련 값이 스레드 1에 저장되고 스레드2에서 실행할 경우 스레드2에 저장
    → 두 스레드가 같은 코드를 실행하고, 이 코드가 하나의 ThreadLocal 변수를 참조하더라도 서로의 ThreadLocal 변수를 볼 수 없음

2. 사용

✅ 방법

  1. ThreadLocal 객체 생성
  2. ThreadLocal.set()으로 현재 스레드의 로컬 변수에 값 저장
  3. ThreadLocal.get()으로 현재 스레드의 로컬 변수 값 조회
  4. ThreadLocal.remove()로 현재 스레드의 로컬 변수 값 삭제
//객체 생성
ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();

//스레드의 로컬 변수에 값 저장
threadLocalValue.set(1);
//스레드의 로컬 변수 값 조회
Integer result = threadLocalValue.get();

//스레드의 로컬 변수 값 삭제
threadLocal.remove();

✅ 예시

public class ThreadLocalExample {

    public static void main(String[] args) {
        MyRunnable sharedRunnableInstance = new MyRunnable();

        Thread thread1 = new Thread(sharedRunnableInstance);
        Thread thread2 = new Thread(sharedRunnableInstance);

        thread1.start();
        thread2.start();

        thread1.join(); //wait for thread 1 to terminate
        thread2.join(); //wait for thread 2 to terminate
    }

}
public class MyRunnable implements Runnable {

    private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();

    @Override
    public void run() {
        threadLocal.set( (int) (Math.random() * 100D) );

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }

        System.out.println(threadLocal.get());
    }

3. 활용

  • ThreadLocal은 한 스레드에서 실행되는 코드가 동일한 객체를 사용할 수 있도록 해줌
    → 스레드와 관련된 코드에서 파라미터를 사용하지 않고 객체를 전파하기 위한 용도로 주로 사용

    • 사용자 인증정보 전파 : Spring Security에서 사용자 인증 정보를 전파하기 위해 사용
    • 트랜잭션 컨텍스트 전파 : 트랜잭션 매니저가 트랜잭션 컨텍스트 전파를 위해 사용
    • 스레드에 안전해야 하는 데이터 보관
  • 스레드 기준으로 동작해야 하는 기능을 구현할 때


4. 주의사항

  • 스레드 풀 환경에서 ThreadLocal 사용 시, ThreadLocal 변수에 보관된 데이터 사용이 끝나면 반드시 해당 데이터 삭제 필요
  • 삭제하지 않을 경우, 재사용되는 스레드가 올바르지 않은 데이터를 참조할 수 있음

📖 참고

profile
기쁘게 코딩하고 싶은 백엔드 개발자
post-custom-banner

0개의 댓글