Skip to content

Memory Barrier example #30

@sso9594

Description

@sso9594
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는 최적화를 위해 서로 관계가 없다고 판단한 코드의 순서를 임의로 바꾼다.

+++
스크린샷 2024-10-10 오후 10 04 07
실행해본 결과도 같이 올립니다!

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions