본문 바로가기
book/modern java in action

Chapter 15 CompletableFuture와 리액티브 프로그래밍 컨셉의 기초 (부제: 쓰레드를 통한 병렬 처리와 쓰레드 풀의 정의 및 기능)

by eunoia_DB 2023. 2. 20.

이번 Chapter를 읽고 정리하면서 쉽게 이해가 가지 않았던 부분들이 많았다. 글 내용의 전반적인 흐름이나

주제 자체가 낯설게 느껴진 것도 있었지만 무엇보다 기본적인 CS 관련 용어를 정확히 알고 이해하지 못했기

때문이라 생각됐다. 그래서 이번 Chapter에 대한 정리를 하기 앞서 간단한 CS 용어를 먼저 정리하려고 한다.

 

 

1. 프로세스(Process)

- 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램

- 운영체제에 의해 메모리 공간을 할당받아 단순 실행 중인 프로그램

 

2. 코어(Core)

- CPU에서 연산 작업을 수행하며 하나의 프로세스만 처리

 

3. 쓰레드(Thread)

- CPU 내에서 실제 작업을 실행하는 주체로 가장 작은 단위

 

 

코어와 쓰레드의 차이?

코어와 쓰레드 둘 다 CPU에서 연산 처리와 관련된 용어이지만 코어는 하드웨어의 물리적인 관점에서, 쓰레드는

소프트웨어의 논리적인 관점에서 구별된다. 일반적으로 하나의 코어에는 하나의 쓰레드가 있지만 하나의 코어에

둘 이상의 쓰레드를 실행할 수 있게 하여 병렬처리 작업 또한 가능하다. 이러한 방식의 작업을 하이퍼쓰레딩이라 부른다.

 

 

 


 

 

 

다음은 프로세스 처리 과정에 대한 책의 내용을 순서대로 나열해 정리했다.

 

 

1) 단일 CPU 컴퓨터도 여러 사용자를 지원할 수 있다.

2) 운영체제는 두 사용자가 각각 자신만의 공간에 있다고 생각할 수 있도록 가상 주소 공간을 각각의 프로세스에 제공한다.

3) 운영체제는 주기적으로 번갈아가며 각 프로세스에 CPU를 할당한다.

 

위와 같이 단일 CPU에서 하나의 코어당 하나의 쓰레드만 사용하게 되면 각각 한 번에 하나의 프로세스만 처리해야

하기 때문에 주기적으로 번갈아가며 CPU를 할당해야 하는 작업을 거쳐야만 할 것이다.

 

하지만 한 개 이상의 쓰레드를 사용한다면 어떨까?

프로세스가 운영체제에 한 개 이상의 쓰레드를 요청하게 되면 본인이 가진 프로세스와 같은 주소 공간을 공유하는

프로세스를 요청하게 되면서 태스크를 동시에 협력 처리하는 것이 가능하게 된다.

 

 

가상 주소 공간?

더보기

- 가상 메모리 기법으로 대부분의 운영체제에 적용

- 프로세스가 참조할 수 있는 주소의 범위이며 하나의 프로세스 당 하나의 주소 공간이 주어짐

- 일반적으로 쓰레드는 프로세스 내의 주소 공간을 공유

 

 

 

멀티 코어를 통한 동시 협력 처리

여러 쓰레드를 활용하면 동시 협력 처리가 가능하다고 했는데 이러한 코어의 형태를 멀티 코어라고 한다.

이론적으로 네 개의 코어를 사용해 병렬 실행하게 되면 싱글 코어를 사용했을 때보다 실행 속도를 네 배 향상할 수 있다.

EX) 백만 개의 자료가 저장한 배열을 처리할 때 반복문 하나를 쓰는 것보다 네 개로 나눠 쓰면 더 빠르다.

       ** 이것은 이론상의 예시이고 실제 적용 시 오버헤드로 인해서 네 배 정도의 향상은 되기 어렵다고 한다.

 

 

 

자바 5의 Executor 프레임워크와 쓰레드 풀

자바 5 이후 쓰레드의 힘을 끌어올리는 기능을 제시했는데 이 기능이 바로 Executor 프레임워크(쓰레드 풀 생성)

와 쓰레드 풀이다. 실제 운영체제로 쓰레드를 만들고 종료시키기까지의 과정에는 비싼 비용이 들고 만들 수 있는

쓰레드의 숫자가 제한되어 있다. 또한 운영체제가 지원하는 쓰레드 수가 초과되면 문제 발생가 발생하기 때문에

계속해서 만들지 않도록 주의해야 한다.이러한 한계점은 쓰레드 풀을 통해 보완될 수 있다.

 

 

 

쓰레드 풀의 동작 과정

 

 

 

쓰레드 풀을 사용하면 미리 저장된 만큼의 작업 쓰레드를 통해 동시 연산 실행이 가능하다. 이를 통해 오버헤드 없이

순서대로 들어온 태스크를 실행할 수 있게 된다. 하지만 정해진 쓰레드 이상의 태스크가 초과로 들어오면 이전에 동시

실행된 태스크 처리가 모두 종료되기까지 기다려야 하기 때문에 하나라도 종료되지 않으면 처리 작업을 하지 않는다.

이러한 지연 상태를 데드락이라 부른다. 따라서 지연 가능성이 있는 태스크를 애초에 스레드 풀에 제출하면 안 된다.

 

 

이러한 문제점 해결을 위해서는 시작된 태스크를 내부 호출이 아니라 외부 호출에서 종료하도록 기다리게 하는 여유로운

방식인 여유로운 포크/조인 사용하면 되는데 이는 비교적 안전하다. 포크 조인이란 분할과 정복과 같은 느낌인데 태스크

처리를 여러 부분으로 나눠 처리하다 나중에 결과를 합치는 것이다. 여유로운 포크/조인의 반대인 엄격한 포크/조인은

이러한 과정이 일련의 과정으로 이뤄져야 하기 때문에 시간 지연이 될 수 있다. 여유로운 포크/조인을 사용하면 유연하게

동시 실행이 가능하지만 문제점은 데이터 경쟁 문제와 데이터 처리가 끝나기도 전에 main 메서드를 반환하여 생기는 문제

다양한 문제점들이 있다. (여유로운 포크/조인과 같은 방식을 비동기 메서드라 부른다)

 

 

 

 

 

 

 

 


Reference

 

참고 도서명: 모던 자바 인 액션

https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4 

https://www.baeldung.com/thread-pool-java-and-guava

https://library.gabia.com/contents/infrahosting/1227/

https://crone.tistory.com/423

댓글