Skip to content

Memory Barrier example #30

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
실행해본 결과도 같이 올립니다!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions