24. 두 엔티티 상호작용의 락 획득 순서 (ABBA 데드락)

난이도 최상 해설 보기 →

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

결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 두 엔티티 상호작용의 락 획득 순서
// ----------------------------------------------------------------------------
// 시나리오 (동시성/메모리 · 서버-클라):
//   - 두 캐릭터(Entity) 사이의 상호작용을 처리한다. 예: 상호 유대(친밀도) 갱신,
//     서로에게 버프 공유, 1:1 아이템 이전 등 "두 객체의 상태를 함께" 바꿔야 하는 작업.
//   - 정합성을 위해 두 엔티티를 모두 잠근 뒤 상태를 갱신한다.
//   - 같은 두 캐릭터 사이에 상호작용이 "양방향으로 동시에" 일어날 수 있다:
//     스레드1 이 Link(x, y), 스레드2 가 Link(y, x) 를 동시에 호출.
//
// 요구사항:
//   - 두 엔티티의 상태는 원자적으로(둘 다 잠근 상태에서) 갱신돼야 한다.
//   - 어떤 순서/방향으로 동시에 호출돼도 서버가 멈추지 않고 진행돼야 한다.
//   - 같은 엔티티끼리(자기 자신) 호출돼도 안전해야 한다.
//
// 과제:
//   이 코드의 잠재적 문제를 모두 찾고, 양방향 동시 호출에서 어떤 일이 벌어지는지
//   설명하고, 수정안과 더 나은 설계를 제시하라.
//   (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

public class Entity
{
    public long          Id;
    public readonly object Lock = new();
    public int           Bond;   // 예시 상태
}

public class BondService
{
    public void Link(Entity a, Entity b)
    {
        lock (a.Lock)                 // (A)
        {
            DoSomeWork();             // 두 락 사이의 약간의 작업(경합 창을 넓힘)
            lock (b.Lock)             // (B)
            {
                a.Bond++;
                b.Bond++;
            }
        }
    }

    private void DoSomeWork()
    {
        // 상태 검증/로깅 등(생략)
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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