응용 프로그램의 Scheduling
위 그림처럼 CPU 코어가 할당된 스레드 작업이 종료될 때는 2가지 경우가 존재한다.
1. 프로그램에 할당된 Time Slice를 모두 소진한다.
2. 유저 레벨의 실행권을 스스로 커널 레벨로 반환한다.
커널모드에서는 유저모드의 다른 프로그램들 중 하나를 선택해서 프로그램 실행을 할당해줘야한다.
해당 작업을 스케쥴링이라고 한다.
어떤 프로그램을 실행할지 스케쥴링의 방법은 상황에 따라 다르다.
유저레벨과 커널레벨간 이동을 컨텍스트 스위칭이라고 부른다.
System Call
프로그램에서 커널의 서비스를 사용하는 방법.
유저레벨에서 실행중이던 프로그램에서 system call을 호출했을 경우, 유저레벨의 실행권을 커널레벨로 반환한다.
// ex) cout 객체 호출
1. 유저모드에서 실행중이던 cout 객체를 호출하여 출력 코드 작성.
2. 유저모드에서 커널모드로 System call.
3. 콘솔에 출력.
이후 스케쥴링에 맞춰 CPU는 다음 스레드로 코어를 할당하고 유저레벨로 진입하여 프로그램을 실행한다.
Sleep
실행권을 포기하고 커널레벨에 반환하는 함수
sleef_for: 지정된 시간동안 스레드의 실행은 차단하는 함수.
-> 스레드가 차단된 후 실행권을 커널에 양도하고 시간이 지나면 스케쥴링에 포함된다.
-> 스케쥴링이 밀릴 수 있으므로, 지정된 시간 이상 스레드의 실행이 차단될 수 있다.
yiled(): 커널에게 실행권을 바로 반환한다.
// 자주 사용하는 코드
// 입력된 시간 후 실행을 요청
// 입력한 시간동안 재스케줄링이 요청되지 않는다.
this_thread::sleep_for(chrono::milliseconds(100));
this_thread::sleep_for(100ms);
// 언제든지 재스케줄링이 되어도 상관없다.
// 바로 실행권을 반환한다.
this_thread::yield();
// this_thread::yield() == this_thread::sleep_for(0ms)
SpinLock에서 코드 한 줄만 추가하면 된다.
class SleepLock {
public:
void lock() {
bool expected = false; // before
bool desired = true; // after
while (_locked.compare_exchange_strong(expected, desired) == false) {
expected = false;
this_thread::sleep_for(0ms);
}
}
void unlock() {
//_locked = false;
_locked.store(false);
}
private:
atomic<bool> _locked = false;
};
'Server > C++' 카테고리의 다른 글
조건변수 (Condition Variable) (0) | 2024.07.30 |
---|---|
커널 오브젝트 Event를 사용한 프로그램 동작 (0) | 2024.07.30 |
스핀락 (Spin Lock) (0) | 2024.07.29 |
volatile 컴파일러 최적화 (0) | 2024.07.29 |
효율적인 락 구현 방법 (0) | 2024.07.29 |