[혼자 공부하는 컴퓨터구조 운영체제] 11장 - CPU 스케줄링

Jieun Jung·2026년 3월 28일

성장일지

목록 보기
2/3
post-thumbnail

작년에 지인들과 스터디로 시작했던 혼공컴운을 아직도 다 못 뗐다는 게 슬퍼지는 요즘이다. 지금은 다들 바빠져서 오프라인으로도 온라인으로도 못 모이지만, 시작한 공부를 끝까지 완주하기 위해 혼자서라도 책을 보며 정리하고 있다. (겸사겸사 이번회차 성장일지를 채우기도...^^;;)

이번 게시글에서는 11장 CPU 스케줄링에 대해 요약하고, 검색과 AI를 통해 Java 백엔드 주니어 개발자가 이와 관련해서 무엇을 더 배우고 생각할 수 있는지를 고민해보았다.

 


 

CPU 스케줄링 개요

💡 운영체제가 프로세스들에게 CPU 자원을 배분하고 실행 순서를 정하는 정책과 과정

  • 다중 프로그래밍 환경에서 CPU 이용률을 극대화하고, 프로세스들을 공평하고 효율적으로 처리하기 위해 필수적인 작업임
  • 문맥 교환(Context Switching)을 통해 어떤 프로세스에 CPU를 할당할지 결정함

 

프로세스 우선순위

💡 우선 순위가 높은 프로세스란 빨리 처리해야하는 프로세스 를 의미한다.

  • 우선순위 확인법
    • 유닉스/리눅스/macOS: ps -el
    • 윈도우: process explorer

 

스케줄링의 개념과 필요성

  • 프로세스는 실행 상태와 대기 상태를 반복하며 실행됨
  • 하지만 프로세스 종류마다 입출력장치를 이용하는 시간과 CPU를 이용하는 시간의 양에는 차이가 있다.
    • 입출력 집중 프로세스 (I/O bound process): 비디오 재생이나 워드 프로세서와 같이 입출력 작업이 많은 프로세스. 실행 상태보다 대기 상태에 머무르는 시간이 더 많음.
    • CPU 집중 프로세스 (CPU bound process): 복잡한 수치 연산이나 그래픽 작업과 같이 연산 작업이 많은 프로세스임. 대기 상태보다 실행 상태에 머무르는 시간이 더 많음.
    • CPU 버스트와 입출력 버스트: 각각 CPU를 이용하는 작업과 입출력장치를 기다리는 작업을 의미한다. 입출력 집중 프로세스는 입출력 버스트가 많은 프로세스, CPU 집중 프로세스는 CPU 버스트가 많은 프로세스다!

스케줄링이 필요한 이유:
모든 프로세스가 CPU를 동일하게 사용하지 않으므로, 운영체제는 각 프로세스의 특성에 맞춰 우선순위(Priority)를 부여한다! 일반적으로 입출력 집중 프로세스의 우선순위가 CPU 집중 프로세스보다 높게 설정된다.
→ 빨리 입출력을 보내고 CPU를 반환하는 것이 효율적이기 때문

 

스케줄링 큐 (Scheduling Queue)

💡 메모리에 적재된 프로세스들을 현재 상태(준비, 대기 등)별로 묶어 관리하는 대기열 자료구조

  • 운영체제가 다음에 실행할 프로세스나 특정 입출력 완료를 기다리는 프로세스를 빠르고 효율적으로 탐색하기 위해 사용함
  • 각 큐는 프로세스의 정보가 담긴 PCB(프로세스 제어 블록)들을 연결 리스트 형태로 묶어서 구현함
  • 준비 큐 (Ready Queue): CPU를 할당받기 위해 기다리는 상태의 프로세스들이 줄을 섬.
  • 대기 큐 (Waiting Queue): 입출력 장치 완료 등을 기다리기 위해 대기 상태로 접어든 프로세스들이 줄을 섬. (장치별로 별도의 큐가 존재함)

 

선점형과 비선점형 스케줄링

구분선점형 (Preemptive)비선점형 (Non-preemptive)
특징운영체제가 강제로 CPU 점유를 뺏을 수 있음프로세스가 종료되거나 스스로 대기 상태가 되기 전까지 점유
장점자원 독점을 막고 모든 프로세스에 골고루 자원 배분 가능문맥 교환에 의한 오버헤드가 적음
단점문맥 교환(Context Switch) 오버헤드가 자주 발생함하나의 프로세스가 자원을 독점하면 나머지 대기 시간이 길어짐
비유급한 일이 생기면 순서를 바꿀 수 있는 병원 응급실한 번 들어가면 끝날 때까지 못 나오는 1인실 화장실

 


 

CPU 스케줄링 알고리즘

 

알고리즘의 종류

FCFS 스케줄링 (First-Come, First-Served Scheduling)

  • 특징: 준비 큐에 도착한 순서대로 CPU를 할당하는 선입 선처리 비선점형 방식
  • 문제점: 실행 시간이 매우 긴 프로세스가 먼저 도착할 경우, 뒤의 짧은 프로세스들의 대기 시간이 비정상적으로 길어지는 호위 효과(Convoy Effect)가 발생함.

SJF 스케줄링 (Shortest Job First Scheduling)

  • 특징: 준비 큐에 있는 프로세스 중 CPU 이용 시간의 길이가 가장 짧은 프로세스부터 실행
    • 기본적으로 비선점형이지만 선점형으로 구현될 수도 있다! (=SRT 스케줄링)

라운드 로빈 스케줄링 (Round Robin Scheduling)

  • 특징: FCFS 방식에 타임 슬라이스(Time Slice) 개념이 추가된 선점형 방식
  • 타임 슬라이스: 각 프로세스가 CPU를 사용할 수 있는 정해진 시간
  • 운용: 정해진 타임 슬라이스 동안만 CPU를 이용하고, 작업이 안 끝나면 큐의 맨 뒤로 이동
  • 주의점: 타임 슬라이스가 너무 크면 FCFS와 다를 바 없고, 너무 작으면 문맥 교환 오버헤드 때문에 성능이 저하됨.

SRT 스케줄링 (Shortest Remaining Time Scheduling)

  • 특징: 최소 잔여 시간 우선 스케줄링이라고도 함. 쉽게 생각하면, SJF의 선점형 버전.
    • 정해진 시간만큼 실행하되, 다음 CPU를 할당할 때는 남은 작업 시간이 가장 적은 프로세스를 선택함.

우선순위 스케줄링 (Priority Scheduling)

  • 특징: 프로세스에 우선 순위를 부여하고, 우선순위가 가장 높은 순서대로 실행함.
    • 우선순위가 같은 프로세스들은 선입선출로 처리
  • 문제점: 우선순위가 낮은 프로세스는 우선순위가 높은 프로세스에 밀려 영원히 실행되지 못하는 기아 현상(Starvation)이 발생할 수 있음.
  • 해결책: 오랫동안 대기한 프로세스의 우선순위를 점차 높이는 에이징(aging) 방식을 활용

다단계 큐 스케줄링(Multilevel Queue Scheduling)

  • 특징: 우선순위 스케줄링에서 발전(?)한 방식.
    • 우선순위별로 여러 개의 큐를 사용 (프로세스 유형 별로 우선순위를 구분하여 실행)
    • 우선순위가 가장 높은 큐에 있는 프로세스들을 먼저 처리
    • 큐별로 타임 슬라이스를 여러 개 지정할 수도 있고, 다른 스케줄링 알고리즘을 사용할 수도 있다.
      • ex) 큐1: 타임슬라이스 5ms, SRT / 큐2: 타임슬라이스 4ms, 라운드 로빈

다단계 피드백 큐 스케줄링 (Multilevel Feedback Queue Scheduling)

  • 특징: 다단계 큐 스케줄링의 발전된 형태. 현대 OS에서 가장 흔하게 사용된다.
    • 기존 다단계 큐 스케줄링에서는 프로세스들이 큐 사이를 이동할 수 없기 때문에 우선순위가 낮으면 계속 연기됨 (=기아 현상)
    • 다단계 피드백 큐 스케줄링은 프로세스가 큐 사이를 이동할 수 있다!
    • 우선순위가 가장 높은 우선순위 큐에 삽입되었다가, 해당 큐에서 실행이 끝나지 않는 다면 다음 우선순위 큐에 삽입되어 실행
    • 너무 오래 기다리고 있는 프로세스가 있다면 점차 우선순위가 높은 큐로 이동시키는 에이징 기법을 적용한다.

기타) 스케줄링 성능 척도

  • 이용률(Utilization): 전체 시간 중 CPU가 일한 시간의 비율 (높을수록 좋음)
  • 처리량(Throughput): 단위 시간당 완료된 프로세스의 개수 (많을수록 좋음)
  • 대기 시간(Waiting Time): 프로세스가 준비 큐에서 기다린 전체 시간의 합
  • 응답 시간(Response Time): 프로세스가 준비 큐에 들어온 후 처음으로 CPU를 할당 받기까지 걸린 시간.

 


 

백엔드 Java 개발자 관점의 추가 고려 사항

JVM 스레드와 OS 스케줄링의 관계

  • Java의 플랫폼 스레드는 운영체제의 네이티브 스레드와 1:1로 매핑되어 실행됨.
  • 운영체제의 CPU 스케줄링 알고리즘이 Java 애플리케이션의 처리량 및 응답 시간에 직접적인 영향을 미침.

문맥 교환(Context Switching) 비용 제어

  • 다수의 클라이언트 요청을 처리할 때 과도한 스레드 생성은 빈번한 문맥 교환을 유발함.
  • 이는 CPU 오버헤드를 증가시키므로, 서버 구성 시 적절한 스레드 풀(Thread Pool) 크기를 설정해야 함.

I/O 집중 프로세스 최적화

  • 백엔드 애플리케이션은 데이터베이스 조회나 외부 API 호출 등 I/O 집중 프로세스의 비중이 큼.
  • 스레드가 I/O 대기 상태일 때 발생하는 자원 낭비를 줄이기 위해 비동기 프로그래밍 활용이 권장됨.

 


 

Java 스레드 상태와 OS 상태 매핑

💡 Java 스레드는 운영체제의 네이티브 스레드에 1:1로 매핑되어 실행된다. (Java 21 가상 스레드의 경우 M:N)
JVM이 스레드 관리를 운영체제에 위임하므로, 두 상태가 완벽히 일치하지는 않는다.

상태 매핑 상세

Java 스레드 상태운영체제 프로세스 상태설명
NEW생성 (Created)객체는 생성되었으나 start() 메서드가 아직 호출되지 않은 상태임.
RUNNABLE준비 (Ready) / 실행 (Running)CPU 할당을 대기 중이거나 현재 CPU에서 실행 중인 상태를 모두 포함함.
BLOCKED대기 (Waiting/Blocked)락(Lock)을 획득하기 위해 모니터 진입을 기다리며 실행이 중지된 상태임.
WAITING / TIMED_WAITING대기 (Waiting/Blocked)다른 스레드의 작업 완료를 기다리거나, 지정된 시간 동안 대기하는 상태임.
TERMINATED종료 (Terminated)스레드의 run() 메서드 실행이 완료되어 생명주기가 끝난 상태임.

백엔드 개발 시 주의점

  • 스레드가 BLOCKED 또는 WAITING 상태로 전환되면 운영체제는 문맥 교환을 수행할 수 있다.
  • 이 과정에서 CPU 자원이 소모되므로, 불필요한 동기화로 인한 병목 현상을 최소화해야 함.

 


 

Java 21 가상 스레드와 문맥 교환 최적화

가상 스레드(Virtual Thread)

💡 기존 1:1 스레드 모델의 한계를 극복하고 문맥 교환 오버헤드를 줄이는 경량 스레드

동작 원리

  • JVM이 다수의 가상 스레드를 소수의 운영체제 스레드(캐리어 스레드)에 매핑하여 다대일(M:N) 관계로 실행함.
  • 개발자는 기존과 동일한 스레드 코드를 작성하면서도 운영체제 스레드 자원을 아낄 수 있음.

문맥 교환 오버헤드 감소

  • 가상 스레드가 I/O 작업으로 인해 대기 상태가 되면, JVM은 해당 가상 스레드를 캐리어 스레드에서 분리(unmount)함.
  • 캐리어 스레드는 대기하지 않고 즉시 다른 가상 스레드의 작업을 이어받아 처리함.
  • 결과적으로 운영체제 수준의 무거운 문맥 교환을 피하고 JVM 내부에서 가볍게 스위칭이 이루어짐.

백엔드 적용 이점

  • 높은 동시성을 요구하는 웹 서버 환경에서 스레드 생성 비용과 메모리 사용량을 획기적으로 줄일 수 있음.

 

profile
백엔드 개발자가 되고 싶어서

0개의 댓글