🙇‍♀️메모리 베리어

A) 코드 재배치 억제 B) 가시성

🪐하드웨어 최적화

하드웨어에서 코드적으로 연관이 없다면 최적화를 위해 코드를 재배치를한다

static int x = 0;
static int y = 0;
static int r1 = 0;
static int r2 = 0;

static void Thread_1()
{
    y = 1; // Store y
    r1 = x; // Load X
}

static void Thread_2()
{
    x = 1; // Store x
    r2 = y; // Load y
}

static void Main(string[] args)
{
    int count = 0;
    while (true)
    {
        count++;
        x = y = r1 = r2 = 0;

        Task t1 = new Task(Thread_1);
        Task t2 = new Task(Thread_2);
        t1.Start();
        t2.Start();

        Task.WaitAll(t1, t2);

        if (r1 == 0 && r2 == 0)
            break;
    }

    Console.WriteLine($"{count}번 만에 빠져나옴");
}

수학적으로는 빠져나올수없지만 하드웨어 최적화로 인해 코드 재배치 발생

static void Thread_1()
{
    r1 = x; // Load X
    y = 1; // Store y
}

이렇게 변환되어 빠져나온다

🪐메모리 베리어로 막기

  • 코드재배치 막기
    • 코드 재배치를 막기위한 선을 만든다!
    • Thread.MomoryBarrier사용
  • MemoryBarrier
    • 1) Full Memory Barrier (ASM MFENCE, C# Thread.MenoryBarrier) : Store/Load 둘 다 막는다
    • 2) Store Memory Barrier (ASM SFENCE) : Store만 막는다
    • 3) Load Memory Barrier (ASM LFENCE) : Load만 막는다
static void Thread_1()
{
    y = 1; // Store y

    // -----------------------
    Thread.MemoryBarrier(); // 위아래 코드 이동 불가

    r1 = x; // Load X
}

static void Thread_2()
{
    x = 1; // Store x

    // -----------------------
    Thread.MemoryBarrier();

    r2 = y; // Load y
}

🪐가시성의 역할

  • 메모리 베리어는 가시성의 역할도 한다

  • 가시성 식당 비유
    • A 직원이 콜라 주문을 받는다
    • A 직원이 주문현황에 올린다
    • B 직원은 주문현황을 보고 수첩을 갱신한다
  • 가시성 화장실 비유
    • 화장실을 사용하고 난 뒤 물을 내린다
    • 다음으로 화장실을 사용하는 사람은 물을 내리고 사용한다

A 쓰레드는 캐시에 내용을 적고 램에 동기화를 함

B 쓰레드는 동기화를 하고 캐시의 내용을 갱신함

static void Thread_1()
{
    y = 1; // Store y

    // -----------------------
    Thread.MemoryBarrier(); // 물내리기 (정보 동기화)

    r1 = x; // Load X
}

static void Thread_2()
{
    x = 1; // Store x

    // -----------------------
    Thread.MemoryBarrier(); // 물내리기 (정보 동기화)

    r2 = y; // Load y
}
  • 메모리 베리어 예시
int _answer;
bool _complete;

void A()
{
    _answer = 123; // store
    Thread.MemoryBarrier(); // Barrier 1 정보를 저장하고 동기화
    _complete = true; // store
    Thread.MemoryBarrier(); // Barrier 2 정보를 저장하고 동기화
}

void B()
{
    Thread.MemoryBarrier(); // Barrier 3 정보를 읽기전 동기화
    if (_complete) // read
    {
        Thread.MemoryBarrier(); // Barrier 4 정보를 읽기전 동기화
        Console.WriteLine(_answer); // read
    }
}

태그:

카테고리:

업데이트: