임계 구역에 진입이 불가능할 때, 진입이 가능할 때 까지 루프를 돌면서 재시도 하는 방식으로 구현된 락.
임계 구역 진입 전까지 루프를 계속 돈다. CPU를 점유하여 무의미한 코드를 계속 수행하면서 임계영역이 언락되길 기다리기 때문에 busy waiting 상태라고 한다.
스핀락은 락을 얻지 못한 스레드가 커널 스케줄러에게 CPU를 양보하지 않고, 그 자리에서 계솓 루프를 돌며 락의 해제를 기다리는 방식이다. 커널이 스레드를 대기 큐로 옮기거나, 다른 스레드를 실행시키기 위한 컨텍스트 스위칭이 일어나지 않는다.
컨텍스트 스위칭이란, CPU가 실행 중인 스레드를 교체하면서 레지스터, 프로그램 카운터 등 문맥 정보를 저장/복원하는 작업이다. 시간이 많이 걸리는 작업이기 때문에, 스핀락은 이 비용을 피하려는 설계를 한 것이다. 따라서 스핀 중인 동안 CPU(정확히는 해당 코어)가 계속 그 스레드만 실행하고 있는 것이다.
사용중인 자원에 대한 대기시간이 짧을 때 유리하다. 즉 공유자원에 대한 경합이 잠깐 동안만 발생하는 경우 효과적이다. 하지만, 만약 자원에 대한 대기시간이 길어질 경우, 반복적으로 기다리게 되면서 CPU가 효과적으로 사용되지 못하게 된다.
또한 멀티코어 시스템에서만 사용가능하다. 싱글코어 시스템에서는 한번 락을 잡은 스레드 A가 임계영역에서 실행중이다가, 컨텍스트 스위칭이 발생하면 다른 스레드 B가 스핀하면서 해당 코어를 점유하고 기다린다. 그런데 컨텍스트 스위칭이 되어야 A가 작업을 끝내고 락을 해제할 수 있기 때문에 B가 CPU를 무한 점유당하는 상황이 발생한다. 즉 데드락이 발생한다.
스핀락과 달리, 락을 얻지 못한 스레드는 CPU를 점유하지 않고 잠들었다가 깨는 방식으로 기다린다.
스레드가 임계영역 진입을 시도하는데, 뮤텍스가 Unlock 상태라면 락을 획득하고 임계영역에 진입하고, 뮤텍스가 Lock 상태라면 OS 스케줄러에 의해 락이 풀릴 때 까지 CPU를 양보하고 대기 큐에서 잠든다.
락이 해제되면, 커널이 대기중인 스레드 중 하나를 깨워서 실행시킨다.
이처럼 커널의 스케줄링 지원을 받기 때문에 컨텍스트 스위칭이 발생한다.
CPU낭비가 없어 좋고, 대기 시간이 긴 경우 효율적이다.
하지만 락 획득/해제 시 커널모드 진입, 스케줄링, 컨텍스트 스위칭 등으로 오버헤드가 크다. 또한 임계영역 접근대기시간이 짧은 경우 오히려 스핀락보다 비효율적이다.
공유자원에 접근할 수 있는 스레드(혹은 프로세스)의 수를 제한하는 동기화 도구이다. 세마포어는 내부적으로 정수형 카운터(counter)와 대기(queue) 구조를 가지며, 이 카운터 값에 따라 접근을 허가하거나 대기시킨다.
P(혹은 wait)연산과 V(혹은 signal) 연산이라는 두 가지 기본 동작으로 구현된다.