KoreanFoodie's Study

[C++ 게임 서버] 1-8. Sleep 개념과 구현 본문

Game Dev/Game Server

[C++ 게임 서버] 1-8. Sleep 개념과 구현

GoldGiver 2023. 7. 12. 21:17

Rookiss 님의 '[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버' 를 들으며 배운 내용을 정리하고 있습니다. 관심이 있으신 분은 꼭 한 번 들어보시기를 추천합니다!

[C++ 게임 서버] 1-8. Sleep 개념과 구현

핵심 :

1. Lock 을 잡을 수 없을 때, 일정 시간 동안 기다리게 할 때 sleep 을 사용한다.

2. Sleep 을 사용하면 일정 시간 동안 해당 쓰레드는 준비 상태에 있다가 다시 돌아온다. 이 시간동안에는 CPU 자원을 사용하지 않는다. 대신 Kernel Space 로 전환되는 과정에서의 비용은 발생한다(컨텍스트 스위칭).

3. yield 는 쓰레드에게 주어진 Time Slice 를 즉시 반납하도록 하며, 스케줄러에게 쓰레드가 어떤 일을 할지 알아서 정해달라고 요청을 하게 된다.

이전에 Lock 구현 이론에서 설명한 것 중 두번째인, '랜덤 시간 후 복귀' 메타가 바로 sleep 이다.

이전 글에서 SpinLock 을 이용해 '무작정 기다리는' 전법을 구현했었는데, 이번엔 일정 시간을 기다리는 Sleep 을 구현할 것이다.

사실 이전 SpinLock 에서 아래와 같이 sleep 을 시키는 코드를 넣어주면 끝이다 🤣

class SpinLock
{
private:
	atomic<bool> _locked = false;

public:
	void lock()
	{
		bool expected = false;
		bool desired = true;

		while (_locked.compare_exchange_strong(expected, desired) == false)
		{
			expected = false;

			// 100ms 동안 대기 상태
			this_thread::sleep_for(std::chrono::milliseconds(100));

			// 아래는 사실 0ms 동안 자는 것과 동일하다. 할당된 Time Slice 를 반납한다는 것을 의미
			this_thread::yield();
		}
	}

	void unlock()
	{
		_locked.store(false);
	}
};

 

쓰레드가 대기 상태로 들어가게 되면, CPU 사용을 더 이상 하지 않고 일정 시간동안 준비 상태로 들어간다.

이 과정에서 Kernel space 에 들어가게 되는데... 검색해보니 OS/CPU 마다 정책이 달라 꼭 Kernel Space 로 들어가지 않을 수도 있다고 한다 😅

 

아참, 좀더 자세히 설명하자면... 아래 그림을 참고하자.

일반적으로 쓰레드는 얼마나 CPU 자원을 쓸 수 있는지 쿠폰(?) 같은 것을 받게 되는데, 이것을 OS 에서는 'Time Slice' 라고 한다. 주어진 Time Slice 를 다 쓰게 되면, 자원을 반납하고 준비 상태로 되돌아가는데...

Sleep 을 사용하면, 자동으로 돌아가도록 하는게 아니라 수동으로 자원을 반납하게 하게 만들 수 있다 😁

참고로, yield 를 사용하면 Time Slice 를 즉시 반납하고 커널 영역으로 쓰레드를 넘겨줘, 스케줄러가 알아서 사용하도록 해 준다 😉

 

좀더 자세한 설명은 이 블로그를 참고하자!

Comments