아래의 경우처럼 두 개의 Thread가 동시에 공유 변수에 값을 저장하고 조회하는 경우가 있다. 시간의 차이로 인해 값의 내용이 원하는 결과로 조회되지 않는다.
아래의 테스트 케이스를 한번 보자.
public class ThreadLocalTest {
@Test
public void test() throws InterruptedException {
User user = new User();
Thread thread1 = new Thread(() -> {
user.setName("hong_1");
sleep(1000);
System.out.println("thread1 user: " + user.getName());
});
Thread thread2 = new Thread(() -> {
sleep(500);
user.setName("hong_2");
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(user.getName());
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Getter
@Setter
public static class User {
private String name;
}
}
- 공유 객체(User)를 사용하여 2개의 Thread에서 사용자를 동시에 생성한다.
- Thread 1에서 이름을 세팅하고 1초간 대기하고 다시 조회한다.
- 생성한 사용자의 이름을 조회할 때 1번 Thread에서 만든 이름(
hong_1
)을 다시 조회하면hong_2
로 출력이 되는 문제가 있다.
ThreadLocal
이 문제는 여러 Thread에서 공유 변수를 사용할 때 발생하는 문제이다. 이러한 문제를 해결하고자 Thread 별로 로컬 변수를 사용할 수가 있는데 그것이 ThreadLocal
이다.
소스 예제를 한번 보자.
@Getter
public static class UserThreadLocal {
private ThreadLocal<String> nameStore = new ThreadLocal<>();
public void setName(String name) {
this.nameStore.set(name);
}
public String getName() {
return this.nameStore.get();
}
}
기존에 String name
으로 저장한 값을 ThreadLocal<String> nameStore
로 저장을 한다.
getter
와 setter
를 ThreadLocal의 get
와 set
을 사용한다.
그리고 테스트 케이스를 작성해보자.
@Test
public void testWithThreadLocal() throws InterruptedException {
UserThreadLocal userThreadLocal = new UserThreadLocal();
Thread thread1 = new Thread(() -> {
userThreadLocal.setName("hong_1");
sleep(1000);
System.out.println("thread1 user: " + userThreadLocal.getName());
userThreadLocal.getNameStore().remove();
});
Thread thread2 = new Thread(() -> {
sleep(500);
userThreadLocal.setName("hong_2");
userThreadLocal.getNameStore().remove();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
결과는 예상한 대로 hong_1
으로 잘 나오는 것을 확인할 수 있다.
주의사항
ThreadLocal은 사용을 하고 나면 반드시 remove()
를 통해 제거를 해줘야 한다. 그렇지 않으면 ThreadPool
을 사용하는 환경에서는 원하지 않는 결과를 가져올 수 있다.
반응형