[게임 서버] 1.11 멀티스레드 게임 서버

업데이트:     Updated:

카테고리:

태그:

이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
게임 서버 프로그래밍 교과서, 배현직 저자

📦 1. 멀티스레딩

👉🏻 항목 11: 멀티스레드 게임 서버

멀티스레드로 서버를 개발하는 경우:

  1. 서버 프로세스를 많이 띄우기 곤란할 때.
    예를 들어 프로세스당 로딩해야하는 게임 정보 등의 용량이 매우 클 때
  2. 서버 한 대 프로세스가 여러 CPU를 동원해야 할 만큼 많은 연산을 할 때
  3. 코루틴이나 비동기 함수를 쓸 수 없고 디바이스 타임이 발생할 때
  4. 서버 인스턴스를 서버 기기당 하나만 두어야 할 때
  5. 서로 다른 방이 같은 메모리 공간을 액세스해야 할 때

CPU1       CPU2       CPU3       CPU4
 │          │          │          │
 ▼          ▼          ▼          ▼
[    게임 서버(공통 데이터, 방 목록 등)    ]
   └ 방     └ 방        └ 방        └ 방
   └ 방     └ 방        └ 방        └ 방
   └ ...    └ ...       └ ...       └ ...
   └ 방     └ 방        └ 방        └ 방

멀티스레드 게임 서버는 잠금 범위를 설정해줄 때, 방 단위로 잠금 범위를 설정하는 것이 적당하다.


// 싱글스레드 서버
class MyGameServer {
	class Room {
		String m_roomName;
		List<Player> m_players;
		List<Character> m_characters;
	}
	map<PlayerID, shared_ptr<Room>> m_roomList;
	String m_serverName;
}
// 멀티스레드 서버
class MyGameServer {
	class Room {
		// 방 뮤텍스 추가
		// 보호: 방 내의 데이터
		CriticalSection m_critSec;
		String m_roomName;
		List<Player> m_players;
		List<Character> m_characters;
	}
	map<PlayerID, shared_ptr<Room>> m_roomList;
	String m_serverName;
	// 서버 뮤텍스 추가
	// 보호: 서버 메인, 방 목록
	// (방 안의 데이터까지는 보호하지 않는다.)
	CriticalSection m_critSec;
}

🔁 작동 방식

예: 게임 서버에서 플레이어 A에 대한 처리를 할 때

MyGameServer.DoSomething(playerID) {
	lock(m_critSec); // 1
	room = m_roomList.find(player); // 2
	unlock(m_critSec); // 3

	lock(room.m_critSec); // 4
	room.DoSomething(playerID); // 5
	unlock(room.m_critSec); // 6
}
  1. 서버 뮤텍스 잠금
  2. 플레이어 A가 있는 방을 방 목록에서 찾음
  3. 서버 뮤텍스 잠금 해제
  4. 방 뮤텍스 잠금
  5. 플레이어 A의 방 안에서 처리할 일을 함
  6. 방 뮤텍스 잠금 해제

위와 같이 흘러간다.


⚠️ 주의 사항

  • 시리얼 병목 주의
  • 교착 상태 주의
  • 파일을 액세스할 때 자주 잠그는 뮤텍스를 잠근 채로 액세스하면, 성능 저하가 자주 발생

→ 임계 영역은 꼭 필요한 범위로만 한정하자.

GameServer 카테고리 내 다른 글 보러가기

댓글남기기