Spin-Waiting

Spin-Waiting

Spin-Waiting 이란?

스핀 대기Spin-Waiting는 스레드 동기화 시 다른 스레드의 신호를 기다릴 때, 스레드를 차단하지 않고Blocking CPU를 지속적으로 사용하면서 대기하는 방법입니다. 이 방식은 짧은 시간 동안 대기할 때 효율적입니다.

동작 원리

  • 일반적인 차단 기반 대기Blocking Wait에서는 스레드가 대기 상태로 들어가고 운영 체제가 해당 스레드의 실행을 일시 중단합니다.
    • 이 과정에서 컨텍스트 전환context switch이 발생하여 CPU 리소스가 낭비될 수 있습니다.
    • 컨텍스트 전환에는 시간이 걸리기 때문에, 아주 짧은 대기 시간에는 비효율적입니다.
  • 스핀 대기Spin-Waiting는 스레드가 차단되지 않고, CPU를 계속 점유하면서 신호나 조건을 확인하기 위해 반복적인 작업loop을 수행합니다.
    • 컨텍스트 전환이 발생하지 않으므로 짧은 대기 시간에는 빠르고 효율적입니다.
    • 그러나 대기 시간이 길어질 경우 CPU 사용률이 급격히 증가하여 비효율적이 됩니다.

스핀 대기와 차단 대기의 비교

특징스핀 대기(Spin-Waiting)차단 대기(Blocking Wait)
대기 방식CPU를 사용하며 루프를 반복스레드를 일시 중단 (컨텍스트 전환 발생)
컨텍스트 전환없음있음
CPU 사용량대기 동안 계속 CPU를 사용CPU 사용량 없음
대기 시간짧은 시간에 적합긴 시간에 적합
적용 대상짧은 대기 시간 (예: 몇 밀리초 이내)긴 대기 시간 (예: 신호나 이벤트가 오래 걸릴 때)

스핀 대기의 구현 예

일반적인 스핀 대기

스핀 대기의 기본적인 형태는 조건을 확인하며 루프를 반복하는 것입니다.

while (!condition)
{
    // 조건이 만족될 때까지 계속 반복
}

2. .NET의 SpinWait 사용

.NET에서는 SpinWait 구조체를 제공하여 스핀 대기를 보다 효율적으로 수행할 수 있습니다.

using System.Threading;
class Program
{
    static bool condition = false;
    static void Main()
    {
        // 스레드 A: 조건을 만족시키는 작업
        new Thread(() =>
        {
            Thread.Sleep(100); // 100ms 후 조건 변경
            condition = true;
        }).Start();
        // 스레드 B: 조건을 기다리는 작업
        SpinWait spinWait = new SpinWait();
        while (!condition)
        {
            spinWait.SpinOnce(); // 스핀 대기
        }
        Console.WriteLine("조건 만족!");
    }
}
  • SpinOnce(): 반복 호출 시 짧은 대기를 수행하며, 반복 횟수에 따라 CPU를 점유하거나 잠시 대기합니다.
  • 스핀 횟수가 많아지면 점점 더 긴 대기를 수행하여 CPU 소모를 줄입니다.

스핀 대기의 효율성과 한계

장점

  • 짧은 대기 시간에 효율적:
    • 컨텍스트 전환이 없으므로, 대기 시간이 짧은 경우 더 빠릅니다.
  • 고성능 애플리케이션에서 유리:
    • 매우 짧은 동기화 대기(마이크로초~몇 밀리초)가 자주 발생하는 경우 적합합니다.

단점

  • CPU 사용량 증가:
    • 대기 동안 CPU를 계속 사용하므로 대기 시간이 길어지면 CPU 자원을 낭비합니다.
  • 긴 대기에는 부적합:
    • 긴 시간 동안 대기해야 하는 경우, 차단 대기를 사용하는 것이 효율적입니다.

스핀 대기와 ManualResetEventSlim

ManualResetEventSlim은 스핀 대기를 내부적으로 활용하여 짧은 대기 시간에 효율적입니다.

스핀 대기 → 차단 대기 전환

  • ManualResetEventSlim은 처음에는 스핀 대기를 사용하여 CPU를 점유하면서 신호를 대기합니다.
  • 스핀 대기 시간이 일정 시간(기본적으로 약 10ms)을 초과하면, 차단 대기로 전환하여 CPU 사용을 줄입니다.

언제 스핀 대기를 사용할까?

  • 짧은 대기 시간(몇 밀리초 이내):
    • 스핀 대기가 적합하며, SpinWaitManualResetEventSlim 같은 구조를 사용할 수 있습니다.
  • 긴 대기 시간:
    • 차단 대기를 사용하는 ManualResetEvent 같은 구조를 사용하는 것이 적합합니다.
  • 고성능이 필요한 경우:
    • CPU 코어가 많고, 매우 짧은 대기가 반복적으로 발생하는 애플리케이션에서 스핀 대기가 효과적입니다.