21. 가방이 가득 찬 상태에서 동시 다중 획득

난이도 하 해설 보기 →

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

결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 가방이 가득 찬 상태에서 보상/획득이 동시에 여러 개 들어오는 상황
// ----------------------------------------------------------------------------
// 시나리오:
//   - 인벤토리(가방)는 고정 칸 수(Capacity)를 가진다. 각 칸은 비어있거나(null)
//     아이템 하나를 담는다.
//   - AddItem: 빈 칸을 찾아 아이템을 넣는다. 빈 칸이 없으면 실패.
//   - 한 플레이어가 거의 동시에 여러 경로로 아이템을 받을 수 있다: 퀘스트 보상,
//     몬스터 드랍, 우편 일괄 수령 등. 이들은 서로 다른 워커 스레드에서 처리될 수 있다.
//
// 요구사항:
//   - 같은 칸에 두 아이템이 들어가 한쪽이 사라지면 안 된다(아이템 유실 금지).
//   - 빈 칸 수보다 많은 아이템이 "성공"으로 처리되면 안 된다(가짜 성공/초과 지급 금지).
//   - 동시 획득에도 자료구조가 손상되거나 정의되지 않은 동작이 나면 안 된다.
//
// 과제:
//   이 코드의 잠재적 문제를 모두 찾고, 왜/어떻게 깨지는지(동시 인터리빙 포함)
//   설명하고, 수정안과 더 나은 설계를 제시하라.
//   (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

using System;
using System.Collections.Generic;

public class Item
{
    public long Uid;
    public int  ItemId;
}

public class Inventory
{
    private readonly Item[] _slots;
    public int Capacity => _slots.Length;

    public Inventory(int capacity) { _slots = new Item[capacity]; }

    // 빈 칸을 찾아 아이템을 넣는다. 성공하면 true.
    public bool AddItem(Item item)
    {
        // (A)
        int free = FindFreeSlot();
        if (free < 0) return false;     // 가득 참
        // (B)
        _slots[free] = item;
        return true;
    }

    private int FindFreeSlot()
    {
        for (int i = 0; i < _slots.Length; i++)
            if (_slots[i] == null) return i;
        return -1;
    }

    // 여러 보상을 한꺼번에 지급. 실제로 들어간 개수를 반환.
    public int AddMany(IEnumerable<Item> items)
    {
        int granted = 0;
        foreach (var it in items)
        {
            // (C)
            if (AddItem(it))
                granted++;
        }
        return granted;
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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