47. 2-스레드 상호 배제의 StoreLoad 재배열: acquire/release로는 부족 (C#)

난이도 최상 해설 보기 →

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

결함 코드 · C#
// 시나리오: 게임 서버의 두 전용 스레드(틱 스레드 T0, 스냅샷 스레드 T1)가
//   공유 버퍼에 "짧고 드물게" 상호 배타적으로 접근해야 한다.
//   운영자는 이 핫패스에서 OS 뮤텍스 비용을 피하려고, 두 스레드 전용의
//   경량 상호 배제(2-스레드 Peterson 방식)를 손수 구현했다.
//   - _want[i] : 스레드 i 가 임계 구역 진입을 원함
//   - _turn    : 경합 시 양보 순번
//
// 요구사항:
//   1) 어느 순간에도 두 스레드가 동시에 임계 구역(공유 버퍼 접근)에 있어선 안 된다(상호 배제).
//   2) 이 코드는 정확히 두 스레드(id 0, 1)만 호출한다.
//
// 참고: Peterson 알고리즘 자체는 "순차 일관(sequential consistency)" 가정에서는
//       상호 배제가 증명된다. 아래 구현은 volatile 필드로 가시성을 준다고 보았다.
//
// 과제: Enter/Exit 를 검토하여, 두 스레드가 동시에 임계 구역에 들어갈 수 있는
//       지점을 (A)(B) 마커로 진단하고, 정확한 수정안을 제시하라.

using System.Threading;

public sealed class TwoThreadLock
{
    private readonly bool[] _want = new bool[2];
    private int _turn;

    public void Enter(int me)
    {
        int other = 1 - me;

        Volatile.Write(ref _want[me], true);        // (A) 진입 의사 게시
        Volatile.Write(ref _turn, other);

        // (B) 상대 의사 + 순번 확인. 상대가 원하고 순번이 상대면 대기(양보).
        while (Volatile.Read(ref _want[other]) && Volatile.Read(ref _turn) == other)
        {
            Thread.SpinWait(1);
        }
        // 여기 도달 = 임계 구역 진입
    }

    public void Exit(int me)
    {
        Volatile.Write(ref _want[me], false);
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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