이 글은 김영한님의 스프링 고급편 강의중 제목과 관련된 부분을 블로그장의 취향대로 요약한 것이며 강의 자료 및 출처는 가장 아래에서 확인할 수 있습니다.
1. CPU가 프로그램을 처리하는 방식

위에 프로그램A와 B예를 들어, 음악 프로그램과 워드 프로그램이 있다.
만약 위에서, CPU코어 1번이 프로그램A의 1,2,3,4를 모두 끝낸후에 프로그램 B를 처리한다면 사용자는 어떨까?
예를들어, 음악 프로그램이 끝난뒤에 워드 프로그램이 실행되면 사용자는 매우 답답할 것이다.
따라서 멀티태스킹이라는 기술이 도입되게 되는데 CPU가 프로그램 A,B를 번갈아서 실행하게 된다.

CPU는 프로그램 A의 일부를 실행하고, B의 일부를 번갈아서 실행하여 마치 동시에 실행되는 것 처럼 빠르게 실행한다.
CPU가 여러개라면?

하나의 CPU를 사용하는 것 보다 동시에 더 많은 작업을 처리할 수 있다.(=멀티프로세싱)
2. 프로세스

운영체제 안에서 실행중인 프로그램을 프로세스라 한다.
프로그램을 실행하면 프로세스가 만들어지고 프로그램이 실행되는데 이를 자바로 비유하면 프로그램은 클래스이고 프로세스는 인스턴스이다.
각 프로세스는 별도의 메모리 공간을 갖기에 서로 간섭하지 않는다.
3. 스레드
public class Operator {
public static void main(String[] args) {
int sum1 = 1;
int sum2 = sum1 + 1;
System.out.println("sum1 = " + sum1);
System.out.println("sum2 = " + sum2);
}
}
위 코드를 위에서부터 내려가며 하나씩 실행하는 흐름, 즉 프로세스의 코드를 실행하는 흐름을 스레드라고 한다.
또한 스레드는 프로세스 내에서 실행되는 작업의 단위이다.
스레드는 단일스레드, 멀티스레드가 존재할 수 있는데 예를 들면 다음과 같다.
프로그램 A : 워드 프로그램
- 스레드1 : 문서 편집
- 스레드2 : 자동 저장
- 스레드3 : 맞춤법 검사
프로그램 B : 유튜브
- 스레드1 : 영상 재생
- 스레드2 : 댓글
프로세스와 연관지어 정리하자면 프로세스는 실행 환경과 자원을 제공하고 스레드는 CPU를 사용해서 코드를 하나하나 실행한다.
💡 멀티 스레드는 동시에 실행되기 때문에 각 스레드간 순서와 실행 기간 모두 보장하지 않는다.
컨텍스트 스위칭
컨텍스트 스위칭은 CPU가 현재 실행 중인 프로세스의 상태를 저장하고 다른 프로세스의 상태를 복원하여 실행하는 것이다.
예를 들어,
1~10000까지 더해야 한다. 스레드를 두개 사용하여 스레드1은 1~5000까지 더하고 스레드2는 5001~10000까지 더해야한다고 가정해보자.
CPU코어가 1개고 스레드를 두개 사용한다면?
스레드1은 1~1000 까지 연산한 상태에서 잠시 멈추고,스레드2를 5001~6001까지 연산하는 식으로 반복할 수 있다.
이때, CPU는 스레드1을 멈추고 다시 실행할 때 어디까지 연산했는지 알아야하기 때문에 이런 반복에서 시간 비용이 들게 된다.
💡실제로 컨텍스트 스위칭에 걸리는 시간은 아주 짧지만, 스레드가 매우 많다면 비용이 커질 수 있다.
💡실무 팁
1.CPU 4개, 스레드 2개
스레드의 숫자가 너무 적으면 모든 CPU를 100%활용할 수 없다. 다만, 스레드가 몇 개 없으므로 컨텍스트 스위칭 비용이 줄어든다.
2. CPU 4개, 스레드 100개
스레드의 숫자가 너무 많으면 CPU를 100% 다 활용할 수 있지만 컨텍스트 스위칭 비용이 늘어난다.
3. CPU 4개, 스레드 4개
스레드와 CPU의 숫자가 동일하여 CPU를 100%활용할 수 있고, 컨텍스트 스위칭 비용도 자주 발생하지 않기에 최적의 상태가 된다.
이상적으로 CPU 코어 수 + 1개 정도로 스레드를 맞추면 특정 스레드가 잠시 대기할 때 남은 스레드를 활용할 수 있다.
그렇다면 CPU 코어 수 + 1개가 무조건 이상적인가? 그렇지않다.
각각의 스레드가 하는 작업은 크게 CPU 바운드 작업 vs I/O 바운드 작업 두개로 나뉜다.
CPU 바운드 작업은 CPU의 연산 능력을 많이 요구하는 작업(계산,데이터 처리,알고리즘 실행 등)을 의미하고
I/O 바운드 작업은 입출력 작업(디스크,네트워크,파일 시스템 등)을 많이 요구하는 작업을 의미한다.
실제로 실무에서는 CPU-바운드 작업보다는 데이터베이스 쿼리 처리,네트워크 통신등 I/O 바운드 작업이 더 많다.
예를 들어, 스레드는 CPU를 1% 정도 사용하고, 대부분 DB 서버에 어떤 결과를 조회하면서 기다린다고 가정해보자.
CPU 코어가 4개있다고해서 스레드 숫자도 CPU코어에 맞추게 되면 CPU를 4%정도만 사용할 것이며, 결국 사용자는
동시에 4명밖에 못받지만 CPU는 4%만 사용하여 CPU가 놀고 있는 사태가 벌어질 수 있다.
결국 이를 인지하지 못하고 스레드 숫자를 늘리면 되는데 스케일업을 하는 사태가 발생하게 된다.
그래서 어떻게 설정하라는 것인가?
CPU-바운드 작업이 많다면 CPU 코어 수 + 1개로 설정하여 스레드를 CPU 숫자에 최적화하고,
I/O바운드 작업이 많다면 성능 테스트를 통해 CPU를 최대한 활용하는 숫자까지 스레드를 생성하되, 너무 많은 스레드를 생성하면 컨텍스트 스위칭 비용도 함께 증가하니 적절한 성능 테스트가 필요하다.
* 출처 자료
김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성| 김영한 - 인프런 강의
현재 평점 5점 수강생 7463명인 강의를 만나보세요. 멀티스레드와 동시성을 기초부터 실무 레벨까지 깊이있게 학습합니다. 멀티스레드, 동시성, 스레드 풀과 Executor 프레임워크, 프로세스와 스레
www.inflearn.com
'Java' 카테고리의 다른 글
| Java) 메모리 가시성 & 자바 메모리 모델(JMM) (1) | 2025.07.23 |
|---|---|
| Java) 인스턴스화를 막으려거든 private 생성자를 사용하라 (3) | 2024.11.07 |
| Java) 생성자나 열거 타입으로 싱글턴임을 보증하라 (1) | 2024.11.05 |
| Java) 생성자에 매개변수가 많다면 빌더를 고려하라 (4) | 2024.11.04 |
| Java) 생성자 대신 정적 팩토리 메서드 (1) | 2024.10.30 |