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 사용을 줄입니다.
언제 스핀 대기를 사용할까?
- 짧은 대기 시간(몇 밀리초 이내):
- 스핀 대기가 적합하며,
SpinWait
나ManualResetEventSlim
같은 구조를 사용할 수 있습니다.
- 스핀 대기가 적합하며,
- 긴 대기 시간:
- 차단 대기를 사용하는
ManualResetEvent
같은 구조를 사용하는 것이 적합합니다.
- 차단 대기를 사용하는
- 고성능이 필요한 경우:
- CPU 코어가 많고, 매우 짧은 대기가 반복적으로 발생하는 애플리케이션에서 스핀 대기가 효과적입니다.