40. 손수 짠 스핀락의 비원자 획득(check-then-set)으로 깨지는 상호 배제 (C#)

난이도 상 해설 보기 →

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

결함 코드 · C#
// 시나리오: 핫패스용 손수 짠 스핀락(spinlock)
//
// 초당 수십만 번 갱신되는 아주 짧은 임계구역(카운터/작은 상태)을 뮤텍스보다 가볍게
// 보호하려고 스핀락을 직접 구현했다. 여러 스레드가 이 락으로 공유 카운터를 늘린다.
//
// 요구사항:
//  - 임계구역에는 한 번에 한 스레드만 들어가야 한다(상호 배제).
//  - N개 스레드가 각각 K번 증가시키면 최종 카운터는 정확히 N*K 여야 한다.
//  - 락으로 보호된 쓰기는 다음에 락을 잡는 스레드에게 온전히 보여야 한다.
//
// 아래 스핀락 구현의 (A)(B) 지점을 검토하라.

using System.Threading;

public sealed class SpinLockNaive
{
    private volatile bool _locked;

    public void Enter()
    {
        while (_locked) { }     // (A) 잠겨 있으면 풀릴 때까지 스핀
        _locked = true;         //     비었으니 내가 잡는다
    }

    public void Exit()
    {
        _locked = false;        // (B)
    }
}

public sealed class Counter
{
    private readonly SpinLockNaive _lock = new SpinLockNaive();
    private long _value;

    public void Increment()
    {
        _lock.Enter();
        _value = _value + 1;    // 임계구역
        _lock.Exit();
    }

    public long Value => _value;
}
내 리뷰 · C#
내 답안 · 자동 저장

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