[24-04-05] Process, Thread 와 동시성과 병렬성

XingXi·2024년 4월 5일
0

기록

목록 보기
21/33

ProcessThread 에 대해 공부했던 내용을
복습하는 하려고 한다.

Process

1. Process 란

실행 중인 프로그램을 의미

  • 프로그램의 실제 실행을 의미한다
  • OS 로 부터 자원을 할당 받는 최소 작업 단위를 말한다.
  • 프로그램의 데이터들이 메모리에 올라와서 명령을 수행하고 있는 상태
  • OS 로 부터 메모리, CPU, 파일, 네트워크 자원을 할당 받으며 독립적으로 실행이 된다.
  • Process 은 독립적이며 Process 간 통신이 어렵다.

2. Process 구조

💡 정적 할당 영역


TEXT( CODE )

  • 실행되는 프로그램의 함수들이 저장되는 영역이다.
  • CPU 에서 여기에 저장된 코드를 하나씩 실행 시킨다.
  • Program Counter 를 사용해서 다음에 실행할 코드 주소를 가리킨다.

DATA

  • 코드가 실행되면서 사용하는 전역변수, static 변수 등의 데이터가 저장되는 공간이다.

💡 동적 할당 영역


HEAP

  • 사용자에 의해 메모리 공간이 동적으로 할당되어 데이터가 저장되는 영역
  • 메모리의 낮은 주소에서 높은 주소로 할당 된다.

STACK

  • 프로그램의 함수 호출 시, 함수의 정보가 저장되는 영역
  • 지역변수, 매개변수, 종료 시 돌아갈 리턴 값 등이 저장 ( 이런 구조를 Stack Frame 이라고 한다 )
  • 함수의 호출이 완료되면 함수 정보가 소멸한다.
  • FIFO : 선입선출 구조로 데이터가 처리 된다.

❓높은 주소, 낮은 주소

메모리가 어디에 할당 되는지 구분을 하기 위해서 정한 개념
낮은 주소에는 정적 리소스 들이 할당 되고, 높은 주소에는 동적 리소스가 할당이 된다.
높은 주소라고 데이터 접근에 이점이 있는 것이 아니며,
메모리 관리와 프로그램 구조 때문에 쉽게 구분하기 위해서 사용한다.



Thread

OS 로 부터 할당 받은 자원을 사용하는 실행단위

  • Process 를 실행 하는 단위, CPU 의 최소 실행단위
  • Thread 마다 독립적으로 실행되며, 프로세스는 하나 이상의 쓰레드를 갖는다
  • process 에서 Heap, Static, Code 영역을 공유 받아서 사용한다.
  • Process 내에서 생성되며, 여러개의 Thread 가 존재 할 수 있다.

❓왜 Thread 는 Process 로 부터 Stack 영역은 공유 받지 않을까?

스레드는 하나의 프로세스 내에서 여러 작업을 동시에 수행하기 위해 사용한다.
각 스레드는 독립적인 실행 경로를 가지며, 서로 다른 함수나 변수를 사용하여 다른 작업을 수행할 수 있다. 스레드 간의 상호 간섭이나 충돌을 방지하기 위해, 실행 중인 스레드는 고유해야한다.
이를 위해 스레드는 독립적인 스택을 가지며, Thread 의 스택은 공유 되지 않는다.



Concurrency ( 동시성 )

Thread 가 두 가지 이상의 일을 처리하는 것

  • 한번에 많은 일을 처리하는 것이 목적이다. ( 효율적으로 사용하기 위함 )
  • 작업을 빠르게 처리하는 것이 목적이 아니다. 여러가지 Program 을 실행시키는 것에 목적을 둔다.
  • 동시에 진행되는 것처럼 인식하지만 사실 빠르게 여러가지 일을 조금씩 반복하고 있는 것이다.

❓ I/O 블록에 걸렸을 때, Thread 는 새로 생성이 되는가?

I/O 블록 처리는 CPU 가 작업을 수행하지 않는다.
그렇다면 Thread 를 새로 생성해서 사용하는 것인가 궁금했다.


답은 주로 비동기적인 방식으로 작업을 처리하여 다른 Process 에게 넘긴다고 한다.
즉, I/O 작업이 수행되는 동안 CPU 는 다른 Thread 에게 일을 할당을 한다.,


A 라는 Thread 에 ‘a’, b’ 라는 일이 있고
B 라는 Thread 에 ‘c’ 라는 일을 할당하여 수행 중 일 때,


before
A : ‘a’, ‘b’
B : ‘c’


B Thread 가 I/O Block 에 빠지게 되면 B가 하고 있던 ‘c’라는 일을
A 가 할당하게 되어 다음과 같은 형태가 된다.


AFTER
A : ‘a’, ‘b’, ‘c’
B : I/O


Parallelism ( 병렬성 )

서로 다른 프로세스가 서로 다른 일을 동시에 수행하는 것

  • CPU 가 동시에 많은 일을 수행하는 것에 중점을 둔다
  • 여러 작업이 동시에 수행하는 것을 말한다.
  • 하드웨어 수준

Example

💡Parallelism

    public static void main(String[] args) {
        
        // 현재 PC 코어 갯수 구하기 

        int coreCnt = Runtime.getRuntime().availableProcessors();
        System.out.println("CORE ( PROCESS )  : "+coreCnt);

        List<Integer> list = new ArrayList<>();
        for(int i = 0; i < coreCnt; i++) {
            list.add(i);
        }

        // START TIME 
        long startTime = System.currentTimeMillis();

        long sum  = list.parallelStream()
                .mapToLong(i -> {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    return i;
                })
                .sum();

        long endTime = System.currentTimeMillis();

        System.out.println("RUNNING TIME: " + (endTime - startTime) + "ms");
        System.out.println("RESULT : " + sum);

        }

Description

CORE ( PROCESS ) : 16
RUNNING TIME: 523ms
RESULT : 120


현재 동작하고 있는 코어의 개수가 16 이고, 그 수만큼 배열에 추가한다.
배열을 순회할 때마다 0.5 초 씩 소요가 됨으로 16 * 0.5 = 8초 정도 소요 될 거라고 예상 하지만
Thread 가 하나씩 할당되어 총 16 쓰레드가 동작하여 병렬처리를 수행하기 때문에
0.5 초 정도 걸렸다.


💡Concurrency

public class Concurrency {
    public static void main(String[] args) {
        
        // 현재 PC 코어 갯수 구하기 

        int coreCnt = Runtime.getRuntime().availableProcessors();
        System.out.println("CORE ( PROCESS )  : "+coreCnt);
        System.out.println("PROGRAM COUNT : "+coreCnt+1);

        List<Integer> list = new ArrayList<>();
        for(int i = 0; i < coreCnt+1; i++) {
            list.add(i);
        }

        // START TIME 
        long startTime = System.currentTimeMillis();

        long sum  = list.parallelStream()
                .mapToLong(i -> {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    return i;
                })
                .sum();

        long endTime = System.currentTimeMillis();

        System.out.println("RUNNING TIME: " + (endTime - startTime) + "ms");
        System.out.println("RESULT : " + sum);

        }

Description

CORE ( PROCESS ) : 16
PROGRAM COUNT : 161
RUNNING TIME: 1020ms
RESULT : 136


현재 동작하고 있는 코어의 개수가 16 이며, 코어 개수 보다 많은 일을 처리한다.
16개의 코어 중에서 1개의 코어는 2개의 일을 해야 하며
동시성이 일어난다.


16개에서 17개로 하나밖에 차이가 나지 않지만,
16 개 일 때는 코어 하나에 하나의 일이 할당 되어 전부 동시에 일을 처리할 수 있지만
17 개 일 때는 하나의 코어가 2개의 일을 할당 받아 동시성이 일어나서
0.5초 가 실행되는 동안 나머지 일에서도 0.5 초 기다리는 로직이 발생하여
발생하는 시간이 약 1초가 걸리는 것을 확인 할 수 있다.

0개의 댓글