[C# 서버] Lock 구현 (Context Switching)

Yerin·2023년 9월 19일

C# 게임 서버

목록 보기
9/13

Lock을 누가 점유하고 있다면?

1) 무작정 기다린다. => SpinLock
2) 나중에 다시 시도한다. (랜덤성) => 쓰레드가 자기 소유권을 포기 Context Switching
3) 운영체제의 도움을 받는다. AutoResetEvent

Context Switching

Thread.Sleep(1);

무조건 휴식 -> 무조건 1ms 정도 쉬고 싶어요

Thread.Sleep(0);

조건부 양보 => 나보다 우선순위가 낮은 애들한테는 양보 불가
=> 우선순위가 나보다 같거나 높은 쓰레드가 없으면 다시 본인한테

Thread.Yield();

관대한 양보 => 관대하게 양보할테니, 지금 실행이 가능한 쓰레드가 있으면 실행하세요
=> 실행 가능한 애가 없으면 남은 시간 소진

SpinLock보다는 무한정으로 루프를 도는 일을 줄일 수 있다.

using System;
using System.Threading;

namespace SeverCore
{
    class SpinLock
    {
        volatile int _locked = 0;

        public void Acquire()
        {
            while (true)
            {  
                // CAS Compare-And-Swap
                int expected = 0;
                int desired = 1;
                if(Interlocked.CompareExchange(ref _locked, desired, expected) == expected)
                    break;
                Thread.Yield(); 
            }
        }

        public void Release()
        {
            _locked = 0;
        }
    }


    class Program
    {
        static int _num = 0;
        static SpinLock _lock = new SpinLock();

        static void Thread_1()
        {
            for (int i = 0; i < 100000; i++)
            {
                _lock.Acquire();
                _num++;
                _lock.Release();
            }
        }
        static void Thread_2()
        {
            for (int i = 0; i < 100000; i++)
            {
                _lock.Acquire();
                _num--;
                _lock.Release();
            }
        }


        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(_num);
        }
    }
}

Context Switching이 반드시 좋은 것은 아니다.
일감을 바꿔치기할 때마다 많은 부담이 들기 때문에!

profile
재밌는 코딩 공부

0개의 댓글