C#/C# 서버

[C#/서버] 메모리 배리어

진서박 2023. 8. 16. 18:27
반응형

인프런 - Rookies님의 강의

https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-mmorpg-%EA%B0%9C%EB%B0%9C-part4

 

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버 - 인프런 | 강의

네트워크/멀티쓰레드/운영체제 등 핵심 전공 지식을 공부하고 게임 서버를 바닥부터 만들어보면서 MMORPG 기술을 학습하는 강의입니다., MMORPG 개발에 필요한 모든 기술, C# + Unity로 Step By Step! 🕹

www.inflearn.com

 

 

다음 코드를 실행했을 때, loop를 빠져나올 수 없을 것 같지만..... r1 == 0, r2 == 0 이 되어 어떻게든 빠져나온다

        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}번 만에 빠져나옴!");
        }

멀티쓰레드 환경에서 이러한 문제가 발생하는데

멀티쓰레드에서는 하드웨어 최적화가 적용된다.

즉, 하드웨어가 쓰레드에 준 연산들이 서로 상관이 없는 연산이라고 생각하면 연산 순서를 임의로 바꿔서 연산하는 경우가 생기게 된다.

 

 

이럴 때 사용되는것이 "메모리 배리어 Memory Barrier" 이다

        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
        }

위와 같이 코드의 재배치를 막고싶은 부분에 Thread.MemoryBarrier() 를 넣어주면 된다.

쉽게 말하자면 군사분계선이다. 위쪽에 있는 코드는 아래쪽으로 넘어올 수 없고, 마찬가지로 아래쪽 코드는 위쪽으로 넘어갈 수 없다.

 

메모리 배리어에는 여러 종류가 있다 (ASM : 어셈블리)

1. Full Memory Barrier (ASM : WFENCE, C# : Thread.MemoryBarrier) : Store/Load 둘다 막음

2. Store Memory Barrier (ASM : SFENCE) : Store만 막음

3. Load Memory Barrier (ASM : LFENCE) : Load 막음

 

메모리 배리어 사용의 이점

1. 코드의 재배치 억제

2. 가시성 확보

 

여기서 가시성은 우리 눈에 보이는 가시성이 아닌, 메모리 상의 가시성을 의미한다.

 

메모리 배리어를 통하여 실제 메모리에 변경사항을 올리고, 다른 쓰레드에서는 변경사항을 받아와서 사용하게 된다.

동기화 작업과 같다.

반응형

'C# > C# 서버' 카테고리의 다른 글

[C#/서버] AutoResetEvent / ManualResetEvent  (0) 2023.08.20
[C#/서버] SpinLock  (0) 2023.08.18
[C#/서버] 캐시 이론  (0) 2023.08.16
[C#/서버] 쓰레드 풀 (ThreadPool)  (0) 2023.08.16
[C#/서버] 쓰레드 (Thread)  (0) 2023.08.16