C#

C# 메모리 베리어.

comwitch 2023. 6. 16. 10:54

C#에서 멀티쓰레딩을 할 때, 각 쓰레드마다 접근 정보를 최신화하는 방식 중 하나로 메모리 베리어가 있다. 

 

하드웨어가 서로 영향을 미치지 않는 연산이 있으면 어셈블리 순서를 임의로 바꿔버리는 행동을 할 때가 있다.

 

C#에서 제공하는 thread memory barrier는 barrier instruction중 save와 load를 양쪽다 베리어를 걸어주는 instruction이 포함되어 있다.

 

wekipedia를 보면 memory barrier insturction은 cpu나 compiler에게 memory operation의 순서를 제약한다고 나와있습니다.

 

코드 예제

 

 

// See https://aka.ms/new-console-template for more information
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ServerCore
{
    //메모리 배리어
    // a. 코드 재배치 억제
    // b. 가시성

    // 1) Full Memory Barrier  s/l 둘다 막는다
    // 2) Store MeMory Barrier : store만 막는다
    // 3) load Memory Barrier : Load만 막는다


    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 y
            Thread.MemoryBarrier();
            r1 = x; // load x
        }

        static void Thread_2()
        {
            x = 1;

            Thread.MemoryBarrier();

            r2 = 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);

                Task.WaitAll(t1, t2);

                //memory barrier가 없으면 다음 구문이 실행이 안된다.
                if (r1 == 0 && r2 == 0)
                    break;
             }

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

        }
    }
}