48. 카피-온-라이트(COW) 라우팅 테이블의 동시 갱신 (C#)
난이도 최상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# — 카피-온-라이트(COW) 라우팅 테이블의 동시 갱신
// ----------------------------------------------------------------------------
// 시나리오:
// 게임서버는 "샤드 ID -> 처리 노드 주소" 라우팅 테이블을 매 요청마다 읽는다(핫패스).
// 읽기가 압도적으로 많고 쓰기는 드물어, 불변 스냅샷을 통째로 교체하는
// 카피-온-라이트 방식을 쓴다: 현재 스냅샷을 복사→수정→원자적으로 교체.
// 갱신(샤드 추가/이전)은 운영 API 나 오토스케일러 등 여러 곳에서 동시에 올 수 있다.
//
// 요구사항:
// - 읽기는 락 없이 일관된 스냅샷을 본다.
// - 동시에 들어온 서로 다른 갱신이 모두 최종 테이블에 반영되어야 한다(유실 금지).
//
// 과제: (A) 지점의 동작을 설명하고, 요구사항을 만족하도록 수정안을 제시하라.
// ============================================================================
using System.Collections.Immutable;
using System.Threading;
public sealed class RoutingTable
{
// 불변 맵을 원자적으로 교체. 읽기는 이 참조를 그대로 읽는다.
private volatile ImmutableDictionary<int, string> _map =
ImmutableDictionary<int, string>.Empty;
// 핫패스 읽기: 락 없이 안전(불변 스냅샷).
public string Resolve(int shardId) =>
_map.TryGetValue(shardId, out var ep) ? ep : null;
// 드문 쓰기: 현재 스냅샷을 읽어 수정본을 만들고 교체.
public void SetRoute(int shardId, string endpoint)
{
var current = _map; // 현재 스냅샷 읽기
var updated = current.SetItem(shardId, endpoint);
_map = updated; // (A)
}
} 결함 코드 · C++
// ============================================================================
// [코드리뷰 문제] C++ — 카피-온-라이트(COW) 라우팅 테이블의 동시 갱신
// ----------------------------------------------------------------------------
// 시나리오:
// "샤드 ID -> 처리 노드 주소" 라우팅 테이블을 매 요청마다 읽는다(핫패스). 읽기가
// 압도적이라 불변 스냅샷을 shared_ptr 로 들고, 갱신 시 현재 스냅샷을 복사→수정→
// 원자적으로 교체한다. 갱신은 운영 API/오토스케일러 등 여러 스레드에서 동시에 올 수 있다.
//
// 요구사항:
// - 읽기는 락 없이 일관된 스냅샷을 본다(수명 안전 포함).
// - 동시에 들어온 서로 다른 갱신이 모두 최종 테이블에 반영되어야 한다(유실 금지).
//
// 과제: (A) 지점의 동작을 설명하고, 요구사항을 만족하도록 수정안을 제시하라.
//
// 빌드: g++ -std=c++17 -pthread problem.cpp
// ============================================================================
#include <atomic>
#include <memory>
#include <string>
#include <unordered_map>
class RoutingTable {
public:
using Map = std::unordered_map<int, std::string>;
RoutingTable() : map_(std::make_shared<const Map>()) {}
// 핫패스 읽기: 스냅샷을 원자적으로 로드(수명 안전).
std::string resolve(int shardId) const {
std::shared_ptr<const Map> snap = std::atomic_load(&map_);
auto it = snap->find(shardId);
return it == snap->end() ? std::string() : it->second;
}
// 드문 쓰기: 현재 스냅샷 복사 → 수정 → 교체.
void setRoute(int shardId, std::string endpoint) {
std::shared_ptr<const Map> current = std::atomic_load(&map_);
auto updated = std::make_shared<Map>(*current); // 복사
(*updated)[shardId] = std::move(endpoint); // 수정
std::atomic_store(&map_, std::shared_ptr<const Map>(updated)); // (A)
}
private:
std::shared_ptr<const Map> map_;
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.