33. 매칭 레이팅 갱신 vs 매칭 진행: 찢긴 스냅샷과 갱신 유실 (C#)
난이도 하 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// [시나리오] 매칭 레이팅 갱신과 매칭 진행의 경합 (서버 내부)
// 플레이어는 매칭 레이팅(Mmr)과 그로부터 파생된 티어(Tier)를 가진다.
// - 매칭 워커: 대기열의 플레이어를 Mmr 로 브래킷(실력 구간)에 배치한다.
// - 매치 결과 워커: 매치가 끝나면 승패에 따라 Mmr 을 조정하고 Tier 를 다시 계산한다.
// 두 종류의 워커는 서로 다른 스레드에서 같은 Player 를 동시에 건드릴 수 있다
// (한 플레이어가 방금 끝난 매치의 정산과, 다음 매치 대기열 배치가 겹치는 순간 등).
//
// [요구사항]
// - 브래킷 배치는 그 시점의 Mmr 과 일관된 값이어야 한다(Mmr 과 Tier 가 어긋나면 안 됨).
// - 여러 매치 결과가 거의 동시에 정산돼도 Mmr 조정이 유실되면 안 된다.
//
// [과제] Matchmaker 의 PlaceInBracket 과 ApplyResult 를 검토하고, 두 워커가
// 같은 플레이어를 동시에 처리할 때 무엇이 어긋나는지 원인과 수정안을
// 제시하라. 표시된 (A)(B) 지점에 주목하라.
using System;
class Player
{
public int PlayerId;
public int Mmr; // 매칭 레이팅
public int Tier; // Mmr 에서 파생
}
class Matchmaker
{
private const int BracketWidth = 100;
private static int ComputeTier(int mmr) => mmr / 500;
// 매칭 워커 스레드에서 호출된다.
public int PlaceInBracket(Player p)
{
// (A)
int mmr = p.Mmr;
return mmr / BracketWidth;
}
// 매치 결과 워커 스레드에서 호출된다(여러 매치가 동시에 끝날 수 있음).
public void ApplyResult(Player p, int delta)
{
// (B)
p.Mmr = p.Mmr + delta;
p.Tier = ComputeTier(p.Mmr);
}
} 결함 코드 · C++
// [시나리오] 매칭 레이팅 갱신과 매칭 진행의 경합 (서버 내부)
// 플레이어는 매칭 레이팅(mmr)과 그로부터 파생된 티어(tier)를 가진다.
// - 매칭 워커: 대기열의 플레이어를 mmr 로 브래킷(실력 구간)에 배치한다.
// - 매치 결과 워커: 매치가 끝나면 승패에 따라 mmr 을 조정하고 tier 를 다시 계산한다.
// 두 종류의 워커는 서로 다른 스레드에서 같은 Player 를 동시에 건드릴 수 있다
// (한 플레이어가 방금 끝난 매치의 정산과, 다음 매치 대기열 배치가 겹치는 순간 등).
//
// [요구사항]
// - 브래킷 배치는 그 시점의 mmr 과 일관된 값이어야 한다(mmr 과 tier 가 어긋나면 안 됨).
// - 여러 매치 결과가 거의 동시에 정산돼도 mmr 조정이 유실되면 안 된다.
//
// [과제] Matchmaker 의 placeInBracket 과 applyResult 를 검토하고, 두 워커가
// 같은 플레이어를 동시에 처리할 때 무엇이 어긋나는지 원인과 수정안을
// 제시하라. 표시된 (A)(B) 지점에 주목하라.
struct Player {
int playerId;
int mmr; // 매칭 레이팅
int tier; // mmr 에서 파생
};
class Matchmaker {
static constexpr int kBracketWidth = 100;
static int computeTier(int mmr) { return mmr / 500; }
public:
// 매칭 워커 스레드에서 호출된다.
int placeInBracket(const Player& p) {
// (A)
int mmr = p.mmr;
return mmr / kBracketWidth;
}
// 매치 결과 워커 스레드에서 호출된다(여러 매치가 동시에 끝날 수 있음).
void applyResult(Player& p, int delta) {
// (B)
p.mmr = p.mmr + delta;
p.tier = computeTier(p.mmr);
}
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.