-
Notifications
You must be signed in to change notification settings - Fork 0
2주차 월요일 그룹 5
- 메모리에 올라간 실행 중인 프로그램
- 메모리에 올라오면 메모리의 운영체제 영역에 PCB가 만들어진다. 문맥 교환 시 PCB에 작업 내용을 저장하고, 복원한다.
- 실행 중인 컴퓨터 프로그램의 인스턴스
프로세스 구성 요소
- 독립된 메모리 공간(가상 주소 공간)
- 운영 체제에서 할당한 시스템 리소스
- 프로그램 코드
- 데이터
- 하나 이상의 실행 스레드(주로 메인 스레드라고도 함)
프로세스의 주요 특징
- 다른 프로세스로부터 격리됨
- 자신만의 기억공간을 가지고 있다
- 생성하고 종료하려면 더 많은 리소스가 필요합니다.
- 프로세스 간 컨텍스트 전환 속도가 느려짐
- 프로세스 간 통신이 더 복잡해졌습니다.
- cpu에서 실행 중인 프로세스의 실행 단위
- 실행을 예약할 수 있는 프로세스의 간단한 하위 집합입니다.
- 동일한 프로세스의 다른 스레드와 동일한 메모리 공간 및 리소스를 공유합니다.
- 생성 및 종료에 필요한 리소스가 더 적습니다.
- 스레드 간 컨텍스트 전환이 더 빨라졌습니다.
- 동일한 프로세스 내의 스레드 간 통신이 더 쉬워졌습니다.
- 단일 프로세스 내에 여러 스레드가 존재할 수 있습니다.
- 프로세스의 PCB와 같이 스레드의 상태를 저장하기 위한 TCB를 가집니다.
- 리소스 사용량: 프로세스는 스레드보다 리소스 집약적입니다.
- 메모리 공유: 동일한 프로세스 내의 스레드는 메모리를 공유하지만 프로세스는 별도의 메모리 공간을 갖습니다.
- 통신: 스레드 간 통신은 프로세스 간 통신보다 간단하고 빠릅니다.
- 격리: 프로세스는 다른 프로세스와 메모리를 공유하지 않으므로 더 나은 격리와 보안을 제공합니다.
- 내결함성: 한 스레드의 충돌은 전체 프로세스에 영향을 미칠 수 있지만 한 프로세스의 충돌은 다른 프로세스에 직접 영향을 미치지 않습니다.
최신 운영 체제에서는 프로세스와 스레드가 모두 프로그램의 멀티태스킹 및 동시 실행에서 중요한 역할을 합니다. 프로세스와 스레드 중 선택은 격리 필요성, 리소스 사용, 프로그램의 여러 부분 간 통신 등 애플리케이션의 특정 요구 사항에 따라 달라집니다.
~ Java5 | Runnable, Thread |
---|---|
Java5 | Callable, Future, Executor, ExecutorService, Executors |
Java7 | Fork/Join, RecursiveTask |
Java8 | CompletableFuture |
Java9 | Flow |
1️⃣ ~ Java5: Thread, Runnable
Thread: 스레드 생성을 위해 Java에서 미리 구현해둔 클래스
Runnable: 스레드의 행위를 정의하는 함수형 인터페이스 (리턴타입X, 파라미터X)
Thread thread1 = new Thread(() -> System.out.println("Thread1: " + Thread.currentThread().getName()));
Thread thread2 = new Thread(() -> System.out.println("Thread2: " + Thread.currentThread().getName()));
thread1.start();
thread2.start();
단점
- Runnable 인터페이스의 스펙상, 값의 반환이 불가하여 관련된 처리에 제약이 있다.
- 스레드 생성을 직접하는 등 저수준 API로 인한 불편함
- 매번 쓰레드 생성과 종료하는 오버헤드가 발생
- 쓰레드들의 관리가 어려움
2️⃣ Java5: Callable, Future, Executor, ExecutorService, Executors
Callable: 스레드의 행위를 정의하는 함수형 인터페이스 (리턴타입O, 파라미터X)
@FunctionalInterface
public interface Callable<V> {
V call();
}
Future: 미래에 완료된 Callable의 반환값을 구하기 위해 사용되는 것. 비동기 작업을 갖고 있어 미래에 실행 결과를 얻도록 도와준다.
즉, 비동기 작업의 현재 상태를 확인 / 기다림 / 결과를 얻는 방법 등을 제공한다.
public interface Future<V> {
boolean isCancelled();
boolean isDone();
V get()
}
Process
-
플랫폼별 구현이 포함된 추상 클래스
-
입출력 관련 자원을 할당 받아 생성됨
- 몇몇 네이티브 플랫폼이 표준 입출력 스트림에 제한된 버퍼 크기만 허용하기 때문에, 입력 스트림을 쓰거나 출력 스트림을 읽을 때 일시적인 실패가 일어나면 하위 프로세스가 차단되거나 교착 상태에 빠질 수도 있다.
-
api
- getInputStream(), getOutputStream(), getErrorStream()
- waitFor(), exitsValue()
- destroy(), destroyForcibly()
- isAlive()
ProcessBuilder
- Runtime.exec()에 비해 프로세스를 생성하는 보다 유연한 방법을 제공합니다..
- 프로세스를 시작하기 전에 프로세스 환경, 작업 디렉터리 및 I/O 리디렉션을 설정할 수 있습니다.
- 동일한 구성으로 여러 프로세스를 만들 수 있습니다.
- api
- command(): 프로세스에 대한 명령과 인수를 설정합니다.
- directory(): 프로세스의 작업 디렉토리를 설정합니다.
- environment(): 프로세스 환경 변수를 수정합니다.
- redirectInput(), redirectOutput(), redirectError(): I/O 리디렉션을 구성합니다.
- start(): 프로세스를 생성하고 시작하여 Process 인스턴스를 반환합니다.
ProcessHandle
- java 9부터 등장
- ProcessHandle은 네이티브 프로세스를 식별하고 제어합니다.
- 각 개별 프로세스의 활성 상태를 모니터링하고, 하위 프로세스를 나열하고, 프로세스에 대한 정보를 얻거나 프로세스를 삭제할 수 있습니다.
- 프로세스 인스턴스는 현재 프로세스에 의해 시작되었으며 프로세스 입력, 출력 및 오류 스트림에 대한 액세스를 추가로 제공합니다.
- 프로세스 상태에 대한 스냅샷을 제공합니다.
- ConcurrentMap 기반 프로세스 ID, 상위 프로세스 및 하위 프로세스에 대한 액세스를 제공합니다.
- api
- current(): 현재 프로세스의 핸들을 가져옵니다.
- of(long pid): 주어진 프로세스 ID에 대한 프로세스 핸들을 가져옵니다.
- children(): 하위 프로세스 핸들의 스트림을 반환합니다.
- parent(): 상위 프로세스 핸들을 반환합니다.
- info(): 명령, 시작 시간, CPU 사용량과 같은 프로세스 정보를 제공합니다.
- onExit(): 프로세스가 종료되면 완료되는 CompletableFuture를 반환합니다.
자바는 다음 세 가지 모델을 사용하여 멀티스레딩 개념을 구현
- Green Thread Model
- Native Thread Model (자바1.3부터)
- Virtual Thread Model (자바21에 추가됨)
1️⃣ Green Thread model
- 특징
- OS 서포트 없이 JVM에 의해서 관리됨
- 애플리케이션 레벨에서 구현되고 사용자 영역에서 관리됨
- 사용자 수준 스레드
- Java 1.3 이전에 사용한 방식으로, 쓰레드를 흉내낸 방식이다.
- 장점
- 동기화와 자원 공유가 수월하고 실행 시간이 짧습니다.
- 즉, User-Level 쓰레드로 VM이나 라이브러리 등으로 개발자가 통제할 수 있다.
- 단점
- 한 번에 하나의 녹색 스레드만 처리할 수 있습니다. 따라서 이 모델을 다대일 모델로 간주하며, 이 때문에 녹색 스레드는 멀티코어 프로세서에서 실행할 수 있지만 여러 코어를 활용할 수는 없습니다.
- CPU Core가 하나인 환경일 때 설계된 방식으로 UserLevelThread가 엄~~~ 청많이 늘어나도 매칭되는 KernelLevelThread는 하나만 만들어져 멀티코어의 장점을 살릴 수 없음
- 이러한 차이로 인해서 그린 스레드 모델은 더 이상 사용되지 않습니다.
- 참고: https://www.geeksforgeeks.org/green-vs-native-threads-and-deprecated-methods-in-java/
2️⃣ Native Thread Model
- 특징
- OS 지원을 받아 JVM에 의해서 관리됨
- OS 레벨에서 구현되고 커널 영역에서 관리됨
- 커널 레벨 스레드
- 모든 윈도우 베이스 OS는 네이티브 스레드 모델을 지원합니다.
- 장점
- 여러 개의 네이티브 스레드가 공존할 수 있습니다. 따라서 다대다 모델이라고도 합니다. 이 모델의 이러한 특성 덕분에 멀티코어 프로세서를 최대한 활용하고 별도의 개별 코어에서 스레드를 동시에 실행할 수 있습니다.
- 자바 구현에 따라 다르지만 보통 일대일 모델로 구현된다함
- GreenThread와는 다르게 여러개의 쓰레드가 자연스럽게 여러개의 코어를 사용할 수 있게 되었다.
- 멀티코어에서 이점
- 동시에 실행되니깐 동시성이슈 발생 가능~
- 여러 개의 네이티브 스레드가 공존할 수 있습니다. 따라서 다대다 모델이라고도 합니다. 이 모델의 이러한 특성 덕분에 멀티코어 프로세서를 최대한 활용하고 별도의 개별 코어에서 스레드를 동시에 실행할 수 있습니다.
- 단점
- 동시에 여러 스레드가 동시에 실행될 수 있기 때문에, 동기화와 자원 공유가 복잡합니다. 이는 스레드의 실행 시간을 증가시킵니다.
- 요청량이 급격하게 증가하는 경우 매번 스레드를 생성하게 되면
컨텍스트 스위칭
비용이 기하급수적으로 증가하게되는 문제발생
3️⃣ Virtual Thread Model
-
특징
- Virtual Thread는 기존 Java의 스레드 모델과 달리, 플랫폼 스레드와 가상 스레드로 나뉩니다. 플랫폼 스레드 위에서 여러 Virtual Thread가 번갈아 가며 실행되는 형태로 동작합니다.
- 마치 커널 스레드와 유저 스레드가 매핑되는 형태랑 비슷합니다.
-
장점
- Virtual Thread는 컨텍스트 스위칭 비용이 저렴하다는 것입니다.-
- Thread는 기본적으로 최대 2MB의 스택 메모리 사이즈를 가지기 때문에, 컨텍스트 스위칭 시 메모리 이동량이 큽니다. 또한 생성을 위해선 커널과 통신하여 스케줄링해야 하므로, 시스템 콜을 이용하기 때문에 생성 비용도 적지 않습니다.
- 하지만 Virtual Thread는 JVM에 의해 생성되기 때문에 시스템 콜과 같은 커널 영역의 호출이 적고, 메모리 크기가 일반 스레드의 1%에 불과합니다. 따라서 Thread에 비해 컨텍스트 스위칭 비용이 적습니다.
-
단점
- 경량화된 모델로 CPU Bound Job에 적합하지 않음
- 컨텍스트 스위칭이 적은 환경에서는 기존 스레드 모델을 사용하는 것이 적합할 수 있음
-
참고자료: OS의 스레드 모델
- 하나의 커널 스레드에 여러 개의 유저 스레드 연결
- 사용자 수준에서의 스레드 관리
- 주로 커널 스레드를 지원하지 않는 시스템에서 사용
- 한 번에 하나의 유저스레드만 커널에 접근가능
- 멀티코어 시스템에서 병렬적인 수행이 불가능
- 하나의 유저 스레드에 하나의 커널 스레드가 대응하는 모델
- Many-to-One방식에서 시스템 호출 시 다른 스레드들이 중단되는 문제를 해결할 수 있어 동시성 향상
- 멀티프로세서 시스템에서는 동시에 여러 개 쓰레드 수행 가능
- 유저 스레드 증가분만큼 커널 스레드가 증가.
- 커널 스레드를 생성하는 것은 오버헤드가 큰 작업이기에 성능저하 발생가능
- 여러 유저스레드가 더 적거나 같은 수의 커널 스레드에 대응하는 모델
- 운영체제에 충분한 수의 커널 스레드를 생성가능
- 커널 스레드의 구체적 개수는 프로그램이나 작동기기에 따라 상이
- 멀티프로세서 프로그램에서는 싱글프로세서 보다 더 많은 커널 스레드가 생성
- 커널이 사용자 스레드와 커널 스레드의 매핑을 적절하게 조절
<출처>
Java의 미래, Virtual Thread https://techblog.woowahan.com/15398/
[운영체제(OS)] 스레드 (Thread), 멀티스레드(Multithreaded Programming)란? https://junhkang.tistory.com/28
Multithreading Models https://docs.oracle.com/cd/E19455-01/806-3461/6jck06gqk/index.html