[C# 서버] Interlocked

Yerin·2023년 9월 19일

C# 게임 서버

목록 보기
5/13

아래와 같이 코드를 실행해보자.

namespace SeverCore
{
    class Program
    {
        static int number = 0;
        

        static void Thread_1()
        {
            for (int i = 0; i < 10000; i++)
                number++;
        }


        static void Thread_2()
        {
            for (int i = 0; i < 10000; i++)
                number--;
        }

        static void Main(string[] args)
        {
            Task t1 = new Task(Thread_1);
            Task t2 = new Task(Thread_2);
            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(number);
        }
    }
}

예상처럼 0이 결과로 뜨는 것을 알 수 있다.

숫자를 100000으로 늘린다면?

왜 이런 결과가 나올까?

경합 조건 (Race Condition)

number++; 부분에 집중해보자.
위 한줄의 코드는 아래 세줄로 해석된다.

int temp = number;
temp +=1;
number = temp;

코드 상으로 볼 때는 한가지 단계로 생각했지만 사실상 세가지의 단계로 이루어진 것이다.

즉 원자성(atomic)의 개념이 중요해진다.

어떤 동작이 한 번에 일어나야한다는 것이다.

Interlocked

이를 해결하기 위해 Interlocked 키워드를 사용하자.
단, Interlocked를 사용할 경우 성능에 영향을 준다는 단점이 있다.

namespace SeverCore
{
    class Program
    {
        static int number = 0;
        

        static void Thread_1()
        {
            for (int i = 0; i < 100000; i++)
                Interlocked.Increment(ref number);
            
        }


        static void Thread_2()
        {
            for (int i = 0; i < 100000; i++)
                Interlocked.Decrement(ref number);
        }

        static void Main(string[] args)
        {
            Task t1 = new Task(Thread_1);
            Task t2 = new Task(Thread_2);
            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(number);
        }
    }
}

Interlocked 키워드 같은 경우 메모리 배리어를 간접적으로 사용하고 있다.
즉 가시성 문제가 해결된다.

Interlocked.Increment(ref number);

number의 값을 참조해서 사용해야하기 때문에 ref로 인자를 받는다.

해당 연산이 지난 후의 값을 이용하고 싶을 경우
아래와 같이 int 인자로 받아 사용한다.

int afterValue = Interlocked.Increment(ref number);

why?) 멀티 쓰레드 환경에서는 number를 다른 누군가가 사용하고 있을 수 있기 때문이다.

profile
재밌는 코딩 공부

0개의 댓글