22. SemaphoreSlim 의 내부 동작과 async 친화적 대기(WaitAsync)

난이도 상 해설 보기 →

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

결함 코드 · C#
// 주제: SemaphoreSlim 의 내부 동작 — lock/Monitor 와 무엇이 다르고, WaitAsync 는
//       "스레드를 블로킹하지 않고 기다린다"는 게 내부적으로 무슨 뜻인가.
//
// 게임서버에서 흔한 패턴: DB/외부 API 호출처럼 동시 호출 수를 제한하고 싶은데,
// 그 호출이 async(비동기 I/O)일 때 lock 으로는 감쌀 수 없다(await 는 lock 블록 안에서
// 쓸 수 없다). SemaphoreSlim 이 그 대안으로 쓰인다.
//
// 다음을 예측·설명하라:
//  (1) SemaphoreSlim(initialCount: 2) 로 동시 진입 2개까지 허용할 때, 3번째 호출자는
//      Wait()/WaitAsync() 중 무엇을 쓰느냐에 따라 "기다리는 방식"이 어떻게 다른가?
//      (스레드풀 스레드를 점유한 채 블로킹 vs 점유하지 않고 대기)
//  (2) (A): 왜 lock(obj) { await ...; } 형태는 컴파일이 안 되거나 의도대로 동작하지 않는가?
//      SemaphoreSlim.WaitAsync() 는 어떻게 이 문제를 우회하는가?
//  (3) (B): Release() 를 호출하는 스레드와 Wait()/WaitAsync() 로 들어간 스레드가 반드시
//      같아야 하는가? lock/Monitor 의 "소유 스레드" 개념과 비교하라(재진입성 포함).
//  (4) SemaphoreSlim 카운트가 0일 때 대기자가 여러 명이면, Release() 한 번에 누가 깨어나는지,
//      그 결정이 내부적으로 어떻게 이뤄지는지 설명하라.

using System;
using System.Threading;
using System.Threading.Tasks;

public static class RateLimitedClient
{
    // 동시에 최대 2개 요청만 외부 API를 호출하도록 제한
    private static readonly SemaphoreSlim s_gate = new SemaphoreSlim(initialCount: 2, maxCount: 2);

    public static async Task<string> CallExternalApiAsync(int requestId)
    {
        // (A) lock(obj) 로는 이 아래 await 를 감쌀 수 없다 — 왜 그런가?
        await s_gate.WaitAsync();
        try
        {
            Console.WriteLine($"[{requestId}] entered gate, thread={Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(100); // 외부 API 호출을 흉내
            return $"result-{requestId}";
        }
        finally
        {
            s_gate.Release();   // (B) Wait 했던 스레드와 Release 하는 스레드가 달라도 되는가?
        }
    }

    public static async Task RunManyAsync(int count)
    {
        var tasks = new Task<string>[count];
        for (int i = 0; i < count; i++)
        {
            int id = i;
            tasks[i] = CallExternalApiAsync(id);
        }
        await Task.WhenAll(tasks);
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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