반응형
문제
class Q1 {
static long value = 123456789123456789L;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
long cnt = 0;
while (true) {
value = (cnt++ % 2 == 0) ? 987654321987654321L : 123456789123456789L;
}
});
Thread t2 = new Thread(() ->{
while (true) {
long v = value;
if (v != 987654321987654321L && v != 123456789123456789L) {
//여기
System.out.println("Something wrong.. value = " + v);
}
}
});
t1.start();
t2.start();
}
}
위 코드의 t2에서 if문 블록은 항상 거짓인가?
항상 v값이 123456789_123456789L
이거나 987654321_987654321L
임이 보장되기 때문에
"//여기" 에 해당하는 블록 내부로 진입할 수 없는가?
정답
그럴 수도 있고, 아닐 수도 있다.
long은 64bit이므로, 32bit 시스템에서 long에 값을 할당하는 것은 원자적이지 않다.
32bit씩 두 번 메모리에 접근해야하기 때문.
따라서 32bit 시스템이라면 문제가 발생한다.
하지만 64bit 시스템이라면 문제가 없다.
따라서, 32bit 시스템이라면 volatile 키워드를 통해 쓰기 쓰레드(t1)가 메모리에 값을 쓰는 작업이 원자성을 가지도록 하여야 한다.
volatile 키워드는 원자성을 나타내는 키워드는 아니고 가시성과 관련된 키워드이지만
어찌되었든 메모리에 값을 원자적으로 할당함을 보장한다.
실제로 문제가 발생한다. (32bit JAVA8)
123456789_123456789는 0x1B6_9B4B_ACD0_5F15 이고
987654321_987654321은 0xDB4_DA5F_7EF4_12B1 이므로
두 값이 섞인 0x1B6_9B4B_7EF4_12B1과 0xDB4_DA5F_ACD0_5F15 값이 섞여 나온다.
카테고리
원자성, 가시성, 멀티쓰레딩, 데이터타입
반응형
'언어 > JAVA' 카테고리의 다른 글
이상하고 아름다운 JAVA 퀴즈 3 (0) | 2023.03.13 |
---|---|
이상하고 아름다운 JAVA 퀴즈 2 (0) | 2023.03.13 |
SOLID 원칙과 구체적인 예시 (0) | 2023.03.09 |
Spring Security JWT 인증 잘 정리된 블로그 (0) | 2022.12.20 |
VSCode Kotlin 프로젝트 셋팅 (0) | 2022.11.22 |