14. 던전 인스턴스 정원 초과 (동시 입장 경합) — C#
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 던전 인스턴스 정원 초과 (동시 입장 경합)
// ----------------------------------------------------------------------------
// 시나리오 (동시성/메모리):
// - 파티/매칭이 잡히면 던전 인스턴스가 생성되고, 정원(capacity, 예: 5)만큼
// 플레이어가 거의 동시에 C_EnterInstance 를 보낸다.
// - 여러 IO/로직 스레드가 같은 인스턴스의 TryEnter 를 동시에 호출한다.
// - 인스턴스에는 정원 초과로 입장시키면 안 된다(6번째는 거부).
// - 같은 플레이어가 더블클릭/재전송으로 두 번 입장 요청할 수도 있다(중복 입장 금지).
//
// 요구사항:
// - 어떤 동시 입장 폭주에서도 members 수는 capacity 를 넘지 않아야 한다.
// - 같은 플레이어는 한 번만 멤버가 되어야 한다.
// - 입장 카운트와 멤버 목록은 항상 일관돼야 한다(부분 반영 금지).
//
// 과제:
// 이 코드의 잠재적 문제를 모두 찾고, 왜/어떻게 깨지는지(경합 인터리빙 포함)
// 설명하고, 수정안과 더 나은 설계를 제시하라.
// (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
using System.Collections.Generic;
using System.Linq;
using System.Threading;
public class DungeonInstance
{
private readonly int _capacity;
private int _count = 0;
private readonly List<long> _members = new List<long>();
public DungeonInstance(int capacity) { _capacity = capacity; }
// C_EnterInstance 처리. 입장 성공 시 true.
public bool TryEnter(long playerId)
{
// (A) 정원 검사
if (Volatile.Read(ref _count) >= _capacity)
return false;
// (B) 중복 입장 검사
if (_members.Contains(playerId))
return false;
// (C) 입장 반영
_members.Add(playerId);
Interlocked.Increment(ref _count);
return true;
}
public int Count => Volatile.Read(ref _count);
} 결함 코드 · C++
// ============================================================================
// [코드리뷰 문제] C++ - 던전 인스턴스 정원 초과 (동시 입장 경합)
// ----------------------------------------------------------------------------
// 시나리오 (동시성/메모리):
// - 파티/매칭이 잡히면 던전 인스턴스가 생성되고, 정원(capacity, 예: 5)만큼
// 플레이어가 거의 동시에 C_EnterInstance 를 보낸다.
// - 여러 IO/로직 스레드가 같은 인스턴스의 TryEnter 를 동시에 호출한다.
// - 인스턴스에는 정원 초과로 입장시키면 안 된다(6번째는 거부).
// - 같은 플레이어가 더블클릭/재전송으로 두 번 입장 요청할 수도 있다(중복 입장 금지).
//
// 요구사항:
// - 어떤 동시 입장 폭주에서도 members 수는 capacity 를 넘지 않아야 한다.
// - 같은 플레이어는 한 번만 멤버가 되어야 한다.
// - 입장 카운트와 멤버 목록은 항상 일관돼야 한다(부분 반영 금지).
//
// 과제:
// 이 코드의 잠재적 문제를 모두 찾고, 왜/어떻게 깨지는지(경합 인터리빙 포함)
// 설명하고, 수정안과 더 나은 설계를 제시하라.
// (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
#include <cstdint>
#include <vector>
#include <atomic>
#include <algorithm>
class DungeonInstance {
public:
explicit DungeonInstance(int capacity) : capacity_(capacity) {}
// C_EnterInstance 처리. 입장 성공 시 true.
bool TryEnter(int64_t playerId)
{
// (A) 정원 검사
if (count_.load() >= capacity_)
return false;
// (B) 중복 입장 검사
if (std::find(members_.begin(), members_.end(), playerId) != members_.end())
return false;
// (C) 입장 반영
members_.push_back(playerId);
count_.fetch_add(1);
return true;
}
int Count() const { return count_.load(); }
private:
const int capacity_;
std::atomic<int> count_{0};
std::vector<int64_t> members_;
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.