(마인크래프트 PE) 게임 서버를 하나 Go로 짜고 있습니다.
(Go/동시성 실습 공부하는 겸 처음 짜는 코드라서 좀 더러울 수 있어요 죄송합니다)
Go를 사용하는 이유가 고루틴과 같은 편리하고 간결한 동시성 프로그래밍 때문이고, 실제로 클라이언트 세션별로 고루틴을 각각 할당하는 방식으로 나름 성능에서 이득을 봤다고 생각합니다.
그런데 동시성 관련해서 경험이 하-나도 없다 보니(뭐 그냥 전체적으로 실력이 부족한 학생이긴 하지만...) 자꾸 여러 문제에 부딛히게 되더라고요.
간략하게 설명하자면 lav7.go의 Players 맵에 Player 구조체들을 저장하고(map[string]*Player), 각 세션에 구조체를 채널로 연결시켜서 패킷을 처리하는 구조입니다. 이 세션들은 각각 독립된 고루틴에서 움직여서 CPU 자원을 최대한 효율적으로 쓰도록 유도했고요.
그런데 서버에 패킷을 Broadcast해야 하거나 각 플레이어간의 시야 체크 등을 할 때, Players 맵을 for range로 순회해서 각 Player 구조체의 SendPacket()을 호출하거나 playerShown 맵을 확인한다거나 해야 하는데, 이러한 활동을 각 플레이어 세션의 고루틴에서 동시에 처리하다 보니 Go race detector에서 경고를 무지막지하게 내보냅니다.
현재 문제가 되는 것은 lav7.go의 Players 맵을 여러 곳에서 동시에 접근한다는 점과, Player 구조체의 playerShown 맵에 다른 구조체에서 접근해야 할 때가 있다는 점입니다. 여기서 Data Race 경고가 발생합니다.
그냥 간단하게 Players 맵과 각 Player 구조체의 playerShown에 뮤텍스를 붙여버리면 안 될까도 생각해봤는데, 이런 식으로 차후에 튀어나올 모든 문제를 해결하다간 데드락이랑 씨름하는 일이 벌어질 것 같고, for range로 Players를 순회하는 동안 락을 계속 쥐고 있으면 성능 손해가 적잖을 것 같기도 하고, Go의 프로그래밍 컨셉에 맞지 않는 것 같아서 좀 더 직관적이고 나은 해결책이 없나 질문합니다. 이런 문제에는 뮤텍스가 답인가요?