41. Interlocked.CompareExchange 기반 락프리 갱신과 ABA

난이도 상 해설 보기 →

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

결함 코드 · C#
// [주제] Interlocked.CompareExchange 기반 락프리 갱신의 내부 동작과 ABA
//
// 게임서버에서 락 경합을 줄이려 CAS(Compare-And-Swap) 루프로 무잠금 갱신을
// 구현했다. 아래 코드의 동작과 내부 동작을 예측·설명하라.
//
// [과제]
//  1) UpdatePeak 의 CAS 루프가 어떻게 "조건부 최댓값 갱신"을 잠금 없이
//     원자적으로 수행하는지, 루프가 왜 필요한지(경합 시 재시도) 설명하라.
//     Interlocked.CompareExchange 의 반환값은 무엇이며 성공/실패를 어떻게 판정하나?
//  2) Interlocked 연산이 제공하는 메모리 순서 보장(가시성/재정렬)은 무엇인가?
//     volatile 읽기만으로 이 갱신을 대체할 수 없는 이유는?
//  3) Pop 의 CAS 루프에는 ABA 문제가 있다. 어떤 인터리빙에서 노드 하나가
//     "그대로인 것처럼" 보여 잘못된 head 가 설정되는지 재현 시나리오로 설명하라.
//  4) "락프리"와 "대기없음(wait-free)"의 차이, 그리고 이 코드가 어느 쪽인지 논하라.

using System.Threading;

public class LockFreeStats
{
    private long _peak;

    public void UpdatePeak(long candidate)
    {
        long observed;
        do
        {
            observed = Interlocked.Read(ref _peak);
            if (candidate <= observed) return;      // 갱신 불필요
        }
        while (Interlocked.CompareExchange(ref _peak, candidate, observed) != observed);
    }
}

public class LockFreeStack<T>
{
    private class Node { public T Value; public Node Next; }
    private Node _head;

    public void Push(T value)
    {
        var n = new Node { Value = value };
        Node old;
        do
        {
            old = _head;
            n.Next = old;
        }
        while (Interlocked.CompareExchange(ref _head, n, old) != old);
    }

    public bool Pop(out T value)
    {
        Node old;
        do
        {
            old = _head;
            if (old == null) { value = default; return false; }
        }
        while (Interlocked.CompareExchange(ref _head, old.Next, old) != old);
        value = old.Value;
        return true;
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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