답변:
일반 잠금 (뮤텍스, 중요 섹션 등)을 사용하면 운영 체제가 스레드를 WAIT 상태로 만들고 동일한 코어에있는 다른 스레드를 예약 하여 선점 합니다. 대기 시간이 정말 짧으면 스레드가 CPU 시간을 다시 받기 위해 선점을 기다려야하기 때문에 성능이 저하됩니다.
게다가, 커널 객체는 인터럽트 핸들러 나 페이징을 사용할 수없는 경우와 같이 커널의 모든 상태에서 사용할 수있는 것은 아닙니다.
스핀 록은 선점을 일으키지 않지만 다른 코어가 잠금을 해제 할 때까지 루프 ( "스핀")에서 대기합니다. 이렇게하면 스레드가 퀀텀 을 잃지 않고 잠금이 해제되는 즉시 계속됩니다. 스핀 락의 간단한 메커니즘을 통해 커널은 거의 모든 상태에서이를 활용할 수 있습니다.
이것이 단일 코어 머신에서 스핀 락이 단순히 스레드 스케줄링을 완전히 방지하는 "인터럽트 비활성화"또는 "IRQL 증가"인 이유입니다.
Spinlock은 궁극적으로 커널이 "Big Kernel Lock"(코어가 커널에 들어갔다가 종료 할 때 해제되는 잠금)을 피하고 커널 기본 요소에 대해 세분화 된 잠금을 갖도록하여 멀티 코어 시스템에서 더 나은 다중 처리를 유발하여 성능을 향상시킵니다.
편집 : 질문이 나왔습니다. "가능하면 스핀 락을 사용해야한다는 뜻입니까?" 그리고 나는 그것에 대답하려고 노력할 것입니다.
앞서 언급했듯이 Spinlock은 예상 대기 시간이 퀀텀 (읽기 : 밀리 초)보다 짧고 선점이 그다지 의미가없는 (예 : 커널 개체를 사용할 수 없음) 장소에서만 유용합니다.
대기 시간을 알 수 없거나 사용자 모드에있는 경우 Spinlock이 효율적이지 않습니다. 스핀 락을 사용할 수 있는지 확인하는 동안 대기중인 코어에서 100 % CPU 시간을 소비합니다. 퀀텀이 만료 될 때까지 다른 스레드가 해당 코어에서 실행되지 않도록합니다. 이 시나리오는 커널 수준의 짧은 버스트에만 가능하며 사용자 모드 응용 프로그램에 대한 옵션은 아닙니다.
리소스가 잠금으로 보호되고 있다고 가정하면 리소스에 액세스하려는 스레드가 먼저 잠금을 획득해야합니다. 잠금을 사용할 수없는 경우 스레드는 잠금이 해제되었는지 반복적으로 확인할 수 있습니다. 이 시간 동안 스레드는 CPU를 사용하여 잠금을 확인하지만 유용한 작업을 수행하지 않고 대기합니다. 이러한 잠금을 스핀 잠금이라고합니다.
특정 조건이 충족 될 때까지 계속되는 루프입니다.
while(cantGoOn) {};
sleep(0)
스레드를 선점하여 처음에 스핀 록을 사용하는 목적을 죽일 것입니다. 다른 스레드에 양보해야하는 경우 일반 잠금을 사용해야합니다. (나는 귀하의 의견이 매우 오래되었지만 다른 사람들이 이것을 제안으로 보지 못하게하고 싶었습니다).
바쁜 기다림 을하는 일종의 자물쇠
매우 낮은 수준의 드라이버 프로그래밍 ( "적절한"대기 함수를 호출하면 몇주기 동안 단순히 바쁜 잠금보다 더 많은 오버 헤드가 발생할 수 있음)를 제외하고는 안티 패턴으로 간주됩니다.
예를 들어 Linux 커널의 Spinlocks를 참조하십시오 .
리소스가 잠길 때 차단하는 대신 바쁜 대기 루프에 들어가 리소스를 풀링하는 것이 더 저렴하다고 생각할 때 스핀 락을 사용하는 것이 좋습니다.
회전은 잠금이 세밀하고 숫자가 많은 경우 (예 : 연결된 목록의 노드 당 잠금) 및 잠금 유지 시간이 항상 매우 짧은 경우에 유용 할 수 있습니다. 일반적으로 스핀 잠금을 유지하는 동안 차단을 피해야합니다. 스스로 차단할 수있는 모든 항목을 호출하고, 한 번에 둘 이상의 스핀 잠금을 유지하고, 동적으로 디스패치 된 호출 (인터페이스 및 가상)을 만들고, 그렇지 않은 코드에 정적으로 디스패치 된 호출을 만듭니다. t 소유 또는 할당 메모리.
성능상의 이유로 SpinLock이 값 유형이라는 점에 유의하는 것도 중요합니다. 따라서 두 인스턴스 (원본 및 복사본)가 서로 완전히 독립적이되어 응용 프로그램의 잘못된 동작을 유발할 수 있으므로 실수로 SpinLock 인스턴스를 복사하지 않도록 매우주의해야합니다. SpinLock 인스턴스를 전달해야하는 경우 값이 아닌 참조로 전달해야합니다.