[TIL] 유데미 . 고성능을 강조한 Java 멀티스레딩, 병행성 및 병렬 실행 프로그래밍 전문가 되기
섹션 1: 개요
1. 개요와 OS 기초
멀티 스레딩 목적과 개요
멀티스레딩이 필요한 이유
응답성
여러 사용자가 동시 요청시 대기 시간을 줄여야함.
즉각적 반응 제공
UI 반응 속도 유지
동영상 플레이어 등 실시간 반응이 필요한 어플
성능
단일 스레드보다 더 많은 작업을 같은 시간 안에 처리할 수 있다.
여러 코어(CPU) 가 있는 경우 병렬로 작업이 가능해져서 처리 속도가 향상된다.
대규모 서비스를 제공하는 경우 서버/컴퓨터 대수를 줄일 수 있다
2. 병행성(Concurrency) 멀티태스킹
병행성
멀티스레딩으로 여러 작업을 동시에 실행하는 듯한 효과 가능
멀티 태스킹
하나의 코어에서 여러 스레드를 빠르게 번갈아가며 실행
사용자 입장에서는 여러 작업이 동시에 수행되는 것처럼 보인다.
여러 코어가 있으면 실제로
병렬 == Parallel
실제로 여러 코어로 여러 작업
병행 == Concurrency
하나의 코어지만 코어 내부의 스레드들도 여러 작업을 수행함.
멀티 스레딩 프로그래밍 주의
스레드 간 공유 데이터 관리 문제, 동기화 문제 발생가능
뮤텍스, 세마포어
등의 동기화 기법을 올바르게 사용해야함
시스템 기본 동작
운영 체제
컴퓨터 전원 ON >> 디스크에서 메모리로 로드되는 특별한 프로그램
애플리케이션 <> 하드웨어(CPU) 간 상호작용을 중재
개발자는 비즈니스 로직에 집중 가능
프로세스(Process)
실행 중인 애플리케이션의
인스턴스
코드, 힙, 파일, 프로세스 ID 등의 메타 데이터로 구성
프로세스 끼리는 서로 격리됨
스레드
프로세스 내부 실행 흐름의 단위
적어도 하나의
메인 스레드
가 존재한다.스레드는 각가
스택
과명령어 포인터
를 가진다스택
함수의 지역 변수, 매개 변수 등을 저장하는 메모리 공간
명령어 포인터
다음에 실행할 명령어 주소
멀티 스레드 어플리케이셔에서
코드, 힙, 파일 등 프로세스 내 자원을 여러 스레드가 공유함.
스레드마다 서로 다른 함수를 동시에 수행 가능함.
2. 운영 체제 기초
컨텍스트 스위치
정의
하나의 스레드 실행을 중단하고 다른 스레드(or 프로세스) 로 전환하는 과정
과정
현재 스레드 레지스터, 캐시, 커널 리소스 상태 저장
전환 대상 스레드 상태 CPU, 메모리에 복원
대략적으로 이런 그림이다
영향
병행성
을 위해 필수적이지만오버헤드
가 발생한다너무 많은 스레드가 동시에 실행되는 경우,
컨텍스트 스위치
가 과도해서져서스래싱(thrashing)
을 유발하게 된다.
프로세스 VS 스레드 전환 비용
프로세스 간 전환
주소 공간이 달라서 리소스 교환 범위가 넓어
비용이 크다
동일 프로세스 내 스레드 전환
공유하는 리소스(코드, 힙 등) 이 많아서
전환 비용이 프로세스 간 전환보다 낮다
운영 체제 스레드 스케쥴링
CPU 코어 < 스레드 개수
운영 체제
가 언제, 어떤 스레드를 실행할 지 결정한다.
스케줄링 기법
First Come First Served(FCFS)
도착 순서대로 실행한다
긴 작업이 먼저 오면 나머지 스레드가 기아(Starvation) 현상이 발생함
매우 짧은 중요도가 높은 작업이 있는데도 불구하고, 긴 작업때문에 병목이 발생함
Shortest Job First(SJF)
짧은 작업부터 실행한다
긴 작업은 계속 뒤로 밀릴 위험이 있음
시간 분할(타임 슬라이스 / 라운드 로빈 ... )
일정 시간 단위(epoke) 로 CPU 시간 분할하여 스레드에 할당한다.
우선순위 기반 동적 스케줄링 기법임
정적 우선순위(개발자 선정) + 동적 보너스(OS 자동 조정)
실시간, 인터랙티브 스레드에 높은 우선순위를 할당한다
이전 에포크에서 실행 시간이 부족했던 스레드도 일정 비율로 보완된다.
내용이 좀 어려운듯
시간분할
놀이기구를 2분씩 번갈아서 타는 행위임.
CPU 도 각 마찬가지로 각 프로그램에 일정 시간을 나눠서 실행 기회를 부여한다
우선순위 시스템
정적 우선순위
VIP 티켓
실시간 채팅앱 같은 프로그램은 더 자주 실행될 수 있도록 한다.
동적 보너스
오래 기다린 손님에게 주는 우선권임
OS 가 자동으로 오래 기다린 프로그램에게 보너스 점수를 부여
보완 시스템
이전에 CPU 를 덜 사용한 프로그램에게 다음 번에 더 많은 기회를 제공함.
4. 멀티 스레드 vs 멀티 프로세스
구분 | 멀티 스레드 접근 | 멀티 프로세스 접근 |
장점 |
|
|
상황 |
|
|
단점 |
|
|
스레드 실습
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("스레드 실행 중 몇번이고: " + Thread.currentThread().getName());
}
});
System.out.println("스레드 실행 이전 몇번이고: " + Thread.currentThread().getName());
thread.start();
System.out.println("스레드 실행 이후 몇번이고: " + Thread.currentThread().getName());
Thread.sleep(10000);
}
}
//
스레드 실행 이전 몇번이고: main
스레드 실행 이후 몇번이고: main
스레드 실행 중 몇번이고: Thread-0
둘다 main 스레드로 찍히는데
이는 스레드가 시작된다고 해서 바로 생기는게 아니라
비동기적으로 생겨나서 여전히 start() 후에도 main 스레드가 출력된다고한다.
실제로 스레드가 run()하는 순간 새 스레드가 생겨남.
에서 보듯이 (라고 했는데 안보이긴함)
메인 스레드는 이미 DestroyJavaVM 에 의하여 종료된 상태고
main 내의 새로운 워커 스레드가 실행 중이라는 것을 알 수 있음.
예외 처리 핸들러 설정 관련
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
throw new RuntimeException("Intentional Exception");
}
});
//예외 처리 핸들러 설정
/*스레드 내에서 발생한 예외를 처리하기 위하여 setUncaughtExceptionHandler() 를 사용가능
*
* 캐치되지 않은 예외가 발생시 지정된 핸들러가 호출되도록 한다.
*
* 왜 쓰냐?
*
* 멀티 스레드에서 각 스레드는 독립적으로 실행되는데
*
* 특정 스레드 내에서 예외가 발생하고 적절하게 처리하지 않는다면,
*
* 해당 스레드는 비정상적으로 종료된다.
*
* 예외 처리 핸들러 설정시 스레드가 비정상적으로 종료되더라도, 애플리케이션 전체가 즉시 종료되지 않고, 다른 스레드들이 계속 정상적으로 동작함.
* */
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("A critical error happened in thread " + t.getName()
+ " the error is " + e.getMessage());
}
});
thread.start();
}
}
//
A critical error happened in thread Thread-0 the error is Intentional Exception
종료 코드 0(으)로 완료된 프로세스
다음 강의
스레드 생성 2부