-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Labels
Description
package thread.control;
import java.util.concurrent.*;
class Program {
static int x = 0;
static int y = 0;
static int r1 = 0;
static int r2 = 0;
static void Thread_1() {
y = 1; // Store
r1 = x; // Load
}
static void Thread_2() {
x = 1; // Store
r2 = y; // Load
}
public static void main(String[] args) throws InterruptedException {
int count = 0;
while (true) {
x = y = r1 = r2 = 0;
count++;
// 두 개의 스레드를 각각 실행
Thread t1 = new Thread(Program::Thread_1);
Thread t2 = new Thread(Program::Thread_2);
// 스레드 시작
t1.start();
t2.start();
// 두 스레드가 모두 끝날 때까지 대기
t1.join();
t2.join();
// r1과 r2가 모두 0이면 루프 탈출
if (r1 == 0 && r2 == 0) {
break;
}
}
System.out.println(count + "번 만에 빠져 나옴!");
}
}
- 다음과 같이 공유자원을 변경하여 if문에 걸려 무한 루프를 돌 것 같은 코드가 있다.
- 하지만 실제로 실행하면 몇번을 실행하든 결국 탈출한다.
- CPU가 코드를 최적화 해버렸기 때문!
- y = 1이 메인 메모리에 즉시 반영되지 않고, r1 = x 가 먼저 반영되어 x 가 0일 수 있다
- 반대의 상황도 마찬가지
- 이 두개가 합쳐져 루프를 탈출
volatile 키워드를 사용하면 write, read 연산에 대해 자동으로 메모리 배리어가 삽입된다.
이외에도
Thread.MemoryBarrier(); // Barrier 1
를 사용해 CPU가 최적화 하지 못하도록 막을 수 있음
CPU는 최적화를 위해 서로 관계가 없다고 판단한 코드의 순서를 임의로 바꾼다.
ruthetum and acs0209
