[게임 서버] 1.11 멀티스레드 게임 서버
카테고리: GameServer
태그: GameServer
이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
게임 서버 프로그래밍 교과서, 배현직 저자
📦 1. 멀티스레딩
👉🏻 항목 11: 멀티스레드 게임 서버
멀티스레드로 서버를 개발하는 경우:
- 서버 프로세스를 많이 띄우기 곤란할 때.
예를 들어 프로세스당 로딩해야하는 게임 정보 등의 용량이 매우 클 때 - 서버 한 대 프로세스가 여러 CPU를 동원해야 할 만큼 많은 연산을 할 때
- 코루틴이나 비동기 함수를 쓸 수 없고 디바이스 타임이 발생할 때
- 서버 인스턴스를 서버 기기당 하나만 두어야 할 때
- 서로 다른 방이 같은 메모리 공간을 액세스해야 할 때
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
}
- 서버 뮤텍스 잠금
- 플레이어 A가 있는 방을 방 목록에서 찾음
- 서버 뮤텍스 잠금 해제
- 방 뮤텍스 잠금
- 플레이어 A의 방 안에서 처리할 일을 함
- 방 뮤텍스 잠금 해제
위와 같이 흘러간다.
⚠️ 주의 사항
- 시리얼 병목 주의
- 교착 상태 주의
- 파일을 액세스할 때 자주 잠그는 뮤텍스를 잠근 채로 액세스하면, 성능 저하가 자주 발생
→ 임계 영역은 꼭 필요한 범위로만 한정하자.
댓글남기기