SpinLock
멀티스레드 환경에서 동기화를 관리하기 위해 사용되는 락(잠금) 메커니즘
공유 자원에 접근하려는 여러 스레드 중 하나만 접근하도록 보장하지만, 대기 중인 스레드가 CPU를 사용하면서 반복적으로 락 상태를 확인하는 방식
user level에서 발생하는 동기화방법
[동작 방식]
1. 락이 풀려있다면 락을 획득하고, 자원을 사용. 락이 걸려 있다면, 다른 스레드가 락을 풀 때까지 계속 반복해서 락 상태 확인
2. 스핀(반복), 락이 풀릴 때까지 기다리면서 반복적으로 상태를 확인하기 때문에 spinlock.
3. 자원을 사용한 스레드는 락을 해제하여 다른 슬드가 자원에 접근할 수 있도록 함
[장점]
: 시스템 호출을 통해 커널 모드로 전환하는 [[#Mutex Lock]] 에 비해 오버헤드가 적음
락이 곧 해제될 가능성이 높을 때(짧은 대기 시간)에 유리함
[단점]
: 대기 중인 스레드가 계속해서 락 상태를 확인하기 때문에, 그 동안 CPU 자원을 소모함. 긴 대기 시간에는 부적합함
[Compare-And-Swap 의사코드]
/* CAS 의사코드
if (_locked == expected)
{
expected = _locked;
_locked = desired;
return true;
}
else
{
expected = _locked;
return false;
} */
[SpinLock 동작 방식]
#include <iostream>
#include <atomic>
using namespace std;
class SpinLock
{
public:
void lock()
{
/* CAS(Compare-And-Swap) : code block을 atomic으로 실행하게끔 묶어주는 매커니즘 */
bool expected = false;
bool desired = true;
/*
expected : _locked이 가지도록 예상되는 값
desired : _locked가 되길 원하는 값.
락이 풀려있을때(false)에만 락을 걸어주는(true) 과정
*/
if (_locked.compare_exchange_strong(expected, desired) == false)
{
/* locked == expected일 때까지 계속 실행 */
/* 매개변수로 bool& 를 받고있기 때문에, expected의 값이 매번 달라짐. 따라서 매번 초기화해줘야함 */
expected = false;
}
}
void unlock()
{
/* _locked = false */
_locked.store(false);
}
private:
/* atomic은 volatile 기능도 포함 */
atomic<bool> _locked = false;
};
Sleep
[실행 - 대기 - 준비] 상태 전환
커널 모드로 실행되기 때문에, Context-Switching을 유발하여 느려질 수 있다
즉, 운영체제한테 공간을 요청하는 System Call을 남발해서는 안된다
현재 lock을 획득할 수 없는 상황이라면, sleep_for을 통해 다른 스레드가 실행될 수 있도록 기회를 제공한다
class SpinLock
{
public:
void lock()
{
/* CAS(Compare-And-Swap) : 하나의 code block을 atomic으로 실행하게끔 묶어주는 매커니즘 */
bool expected = false;
bool desired = true;
if (_locked.compare_exchange_strong(expected, desired) == false)
{
expected = false;
/* 100ms 동안 대기 후 다시 스케줄링 대상으로 포함 */
/* this_thread::sleep_for(std::chrono::milliseconds(100)); */
this_thread::sleep_for(100ms);
/* timeslice를 반환 후 대기 */
this_thread::yield();
}
}
void unlock()
{
_locked.store(false);
}
private:
atomic<bool> _locked = false;
};
'서버 > 공부' 카테고리의 다른 글
Mutex Lock (0) | 2024.12.12 |
---|