while(true)
{
int origin = Interlocked.CompareExchange(ref _lock, 1, 0);
if (origin == 0)
break;
}
SpinLock이란 지난번에 사용했던 구조 자체를 의미 하는 것이 아니다. interlock에서 획득을 시도하고, 실패 시 다시 도전하며 반복하는 것을 SpinLock이라 한다.
지난 번 요약했던 Lock의 세가지 상태 중 2번 째인 대기 상태의 '쉬다가 다시 획득을 시도하는 것' 에 대한 실습이다.
구조 자체는 동일하지만 여기서 Thread.Sleep()
, Thread.Yield()
와 같이 잠깐 쉬거나 다른 쓰레드들에게 양보 해주며, 이때 Context Switching이 발생하게 된다.
이번 강의에서 배워야할 것은 이 Context Switching이 일어나는 과정이다.
Thread 간의 Context Switching이 일어나게 되면, 우선 제어권 자체가 OS 커널에 넘어갔다가 다른 Thread로 넘어가게 되며 큰 비용이 발생하게 되고
기존 Thread에서 작업하던 것을 저장(RAM에)하고, 불러올 때 다시 저장해놨던 메모리를 레지스터를 통해 복원하는 등과 같이 단순한 쓰레드간의 이동이 아닌 이와 같은 과정들이 필요하다.
복잡한 과정이긴 하지만, 경우에 따라 이러한 방법이 최선이 될 수 있다.
예를 들어 아래 처럼 오래 걸리는 동작들이 담겨 대기의 기간이 긴 코드가 있다고 가정했을 때 SpinLock의 구조와 같이 계속 빙글뱅글 돌며 막 시도를 하면 낭비가 심하지만
while(true)
{
// 오래 걸리는 동작
// 대충 획득 시도하는 코드
}
오래 걸릴 것을 예상하고 Thread.Sleep(10000)
을 쉬고 다시 획득을 시도한다면, 위의 경우보다는 더 효율적이게 작동할 수도 있다.
항상 말하는거 같지만, 뭐든 상황에 맞게 잘 사용하면 될 거 같다.