28. 공유 설정의 제자리 수정과 안전 공개(찢긴 스냅샷) (C#)

난이도 최상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 시나리오: 서버가 런타임에 월드/밸런스 설정을 갱신한다(핫 리로드).
//   - 갱신 스레드가 현재 설정 객체의 필드를 새 값으로 바꾼다.
//   - 다수 워커 스레드가 매 틱 _current 의 필드를 읽어 처리한다.
//
// 요구사항:
//   - 워커는 항상 "일관된 하나의 설정 스냅샷"을 본다(필드 간 불일치/찢긴 상태 금지).
//   - 갱신(쓰기)과 읽기가 동시에 일어나도 안전해야 한다.
//
// 참고: C# 에서 "참조 형식 변수에 대한 대입"은 원자적이라 참조가 찢기지는 않는다.
//       그렇다면 이 코드는 안전한가? 아래 (A)(B) 가 동시에 일어날 때를 보라.
//
// 과제: 이 갱신 방식이 동시 환경에서 왜 깨지는지 (A)(B) 지점을 중심으로 진단하고
//       고쳐라. (C++ 트윈과의 언어 차이도 설명할 것.)

using System.Collections.Generic;

public sealed class Config
{
    public int Version;
    public List<int> DropTable = new();
    public string MapName = "";
}

public sealed class World
{
    private Config _current = new Config();

    public int RollDrop(int seed)
    {
        Config c = _current;                              // (A) 스냅샷 의도
        int n = c.DropTable.Count;                        // (A) 필드 읽기 1
        return n == 0 ? 0 : c.DropTable[seed % n];        // (A) 필드 읽기 2 (같은 c)
    }

    // 갱신 스레드: 현재 설정 객체를 "제자리(in place)"에서 수정
    public void Reload(int version, List<int> drops, string map)
    {
        _current.Version = version;                       // (B) 제자리 수정
        _current.DropTable = drops;                       // (B) 제자리 수정
        _current.MapName = map;                           // (B) 제자리 수정
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.