공부/게임 서버

[게임서버] Context Switching이란? (Thread.Sleep(1), Thread.Sleep(0), Thread.Yield())

돌멩이수프 2022. 5. 26. 16:09
728x90

영화를 보다가 화장실에 가고 싶은데 다른 사람이 변기를 차지하고 안에서 잠금장치를 걸었다면 우리는 고민한다.

1. 사람이 나올 때까지 그 앞에서 계속 기다릴지

2. 잠시 자리로 돌아갔다가 나중에 다시 와서 다시 문을 두드릴지

3. 영화관 직원에게 부탁하여 화장실에 자리가 나면 나에게 알려달라고 할지

 

두 번째 상황이 바로 Context Switching이다. Context Switching이란 작업을 진행 중인 스레드가 자신의 작업이 완료되지 않은 상황에서 자신의 작업을 잠시 저장하고 다른 스레드에게 CPU 점유권을 양보하는 작업을 말한다.

 

C#으로 작성된 내용입니다.

using System;

namespace ServerStudy
{
    class Lock
    {
        volatile int _locked = 0; // volatile 변수는 최적화에서 제외되고 항상 메모리에 접근함

        public void Acquire()
        {
            while (true)
            {
                int expected = 0;
                int desired = 1;
                if (Interlocked.CompareExchange(ref _locked, desired, expected) == expected)
                    break;

                //Thread.Sleep(1);
                //Thread.Sleep(0);
                Thread.Yield();
            }
        }

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

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

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

 

결과는 SpinLock과 다를 게 없지만 Thread.Sleep(1), Thread.Sleep(0), Thread.Yield()가 추가되었다. Thread.Sleep(N)은 N 밀리초 만큼 스레드를 멈추라는 뜻이다. 그러나 Sleep(0)은 다른 뜻을 가진다.

 

·Thread.Sleep(1)

다른 스레드에게 CPU 점유권을 양보하라는 뜻이다. 스레드 간 우선순위는 신경쓰지 않는다. (1밀리초만큼 스레드를 멈춤)

·Thread.Sleep(0)

자신과 다른 스레드 중 우선순위가 높은 스레드에게 CPU 점유권을 양보한다. 자신보다 우선순위가 높은 스레드가 없거나, 다른 스레드와 자신의 우선순위가 같다면 자신에게 점유권이 돌아간다.

 

·Thread.Yield()

지금 실행 가능한 다른 스레드가 있으면 그 스레드를 바로 실행한다. 실행 가능한 스레드가 없으면 자신이 대기한다.

728x90