스레드, 멀티스레드, 프로세스, 멀티프로세스

서이·2023년 4월 16일
0

개념정리

목록 보기
2/9

프로세스(process)란?
프로세스란 단순히 실행 중인 프로그램이라고 할 수 있다.
즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 말한다. 이러한 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원 그리고 스레드로 구성된다.


스레드란(thread)란?
스레드란 프로세스 내에서 실제로 작업을 수행하는 주체를 의미한다.
모든 프로세스에는 한 개 이상의 스레드가 존재하며 작업을 수행한다.
또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스라고 한다.

  • 스레드는 각자 자신의 Stack 영역을 보유한다(최소한 자신의 레지스터 상태를 보유한다)
    (레지스터;레지스터는 CPU(Central Processing Unit)가 요청을 처리하는 데 필요한 데이터를 일시적으로 저장하는 기억장치이다)
  • 스레드는 프로세스 내에서 Code, Data, Heap 영역을 공유한다.
  • 스레드를 생성하고 switching 하는 것은 inexpensive하다.

스레드의 장점

  • 응답성
    - 하나의 스레드가 blocked 상태인 동안(I/O를 기다리거나)에서도 다른 스레드가 실행(running)되어 빠른 응답성을 가질 수 있다.
    - (예) 크롬같은 웹 브라우저에서 렉이 걸릴 때 이미지보다 글이 먼저 불러와지는 것과 비슷하다. 그림을 가져오는 것은 blocked이지만 text를 가져오는 것은 따로 진행되기 때문에 글이라도 먼저 볼 수 있는 것이다.

  • 자원 공유
    - code 영역, data 영역, OS resources 들을 공유하여 자원을 효율적으로 사용한다.

  • 경제적
    - 스레드를 생성하는 것이 프로세스를 생성하는 것보다 비용이 적다.
    - 프로세스 간의 문맥 교환은 스레드 간의 문맥 교환보다 오버헤드가 더 크다.
    (프로세스 문맥 교환시 TLB가 flush 되기 때문. 스레드는 Stack 영역만 처리하면 된다.)

  • 병렬성

    • 멀티 코어 환경에서 서로 다른 스레드가 서로 다른 CPU에서 병렬적으로 처리되어 높은 처리율과 성능 향상을 기대할 수 있다.
      - 커널의 도움없이 상호간에 통신이 가능
      - Stack을 제외한 메모리 공간을 공유하므로 스레드간 통신이 간단하다.

주의점
1.각 스레드가 Stack을 제외한 메모리 공간을 공유하기 때문에 동기화 문제가 발생할 수 있다.
2.하나의 스레드에 문제가 발생하면 프로세스 전체가 영향을 받는다.
3.주의 깊은 설계가 필요하며 디버깅이 까다로움 (프로그래머의 역량)


스레드와 프로세스 차이는

  • 프로세스는 각자 프로세스간의 통신에 IPC가 필요하다. 스레드는 스레드 간의 통신에 IPC가 필요하지 않다.
    (IPC; 프로세스 간 통신, 프로세스들끼리 서로 데이터를 주고 받는 행위, 또는 방법을 뜻한다.)

  • 각 프로세스는 Code, Data, Heap, Stack 영역을 각자 보유한다. 스레드는 Code, Data , Heap 영역은 공유하고 Stack 영역만 각자 보유한다.

  • 프로세스 생성과 context switching에 많은 비용이 들어가는 반면 스레드는 생성과 context switching에 적은 비용이 들어간다.
    (context switching; 여러 개의 프로세스가 실행되고 있을 때 기존에 실행되던 프로세스를 중단하고 다른 프로세스를 실행하는 것. 즉, CPU에 실행할 프로세스를 교체하는 기술이다.


멀티 프로세스와 멀티 스레드 차이
멀티 프로세싱은 여러 개의 프로세스가 각자 하나의 작업을 맡아 처리하는 것을 뜻한다. 멀티 스레딩은 여러 개의 스레드가 각자 하나의 작업(task)을 맡아 처리하는 것을 말한다. 둘은 다음과 같은 차이들이 존재한다.

  • 멀티 프로세싱
    • Context Switching이 발생하면 캐시에 존재하는 모든 데이터를 리셋하고 다시 캐시 정보를 불러와야한다. 즉, Context Switching의 오버헤드가 커서 비용이크다.
    • 프로세스 간의 통신에 복잡한 IPC를 사용하여 통신해야 한다.
    • 여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스에만 이상이 생기고 다른 프로세스에는 영향을 주지 않는 장점도 존재한다.
  • 멀티 스레딩
    • 시스템 자원 소모가 감소한다 프로세스를 생성하는 system call이 줄어들어 자원을 효율적으로 관리할 수 있다.
    • 시스템 처리량(Througput)이 증가한다. concurrency와 parallelism을 얻을 수 있기 때문에 효율적이다.
    • 프로세스 내의 Data, Code, Heap 영역을 공유하기 때문에 스레드 간의 통신이 간단하다.
    • 스레드 간의 자원을 공유하기 때문에 동기화 문제(Synchronize problem)가 발생한다.
    • 디버깅이 까다롭다.
    • 하나의 스레드에 문제가 발생하면 전체 프로세스에 영향을 준다.

스레드의 생성과 실행
자바에서 스레드를 생성하는 방법에는 다음과 같이 두가지 방법이 있다.

1.Runnable 인터페이스를 구현하는 방법
2.Thread클래스를 상속받는 방법

두 방법 모두 스레드를 통해 작업하고 싶은 내용을 run() 메소드에 작성하면 된다.

다음 예제는 위의 두가지 방법을 사용하여 스레드를 생성하고 실행하는 예제이다

class ThreadWithClass extend Thread{
	public void run() {
    	for(int i = 0; i< 5; i++){
        	System.out.println(getName()); // 현재 실행 중인 스레드의 이름을 반환
            try {
            	Thread.sleep(10); // 0.01초간 스레드를 멈춤
            } catch (InterruptedExeption e){
            	e.printStackTrace();
            }
        }
    }
}
class ThreadWithRunnable implements Runnable{
	public void run() {
    	for(int i = 0; i<5; i++) {
        	System.out.println(Thread.currentThread().getName());
            try{
            	Thread.sleep(10);
            }catch (InterruptedException e) {
            	e.printStackTrace();
            }
        }
    }
}
public class Thread01 {
	public static void main(String[] args){
    	ThreadWithClass thread1 = new ThreadWithClass();
        Thread thread2 = new Thread(new ThreadWithRunnable());
        
        thread1.start(); // 스레드의 실행
        thread2.start(); // 스레드의 실행
    }
}
// 실행결과

Thread-0
Thread-1
Thread-0
Thread-1
Thread-0
Thread-1
Thread-0
Thread-1
Thread-0
Thread-1

위 예제의 실행 결과를 살펴보면, 생성된 스레드가 번갈아 실행되고 있는 것을 확인할 수 있다.
Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없으므로, 일반적으로 Runnable 인터페이스를 구현하는 방법으로 스레드를 생성한다.

Runnable 인터페이스는 몸체가 없는 메소드인 run() 메소드 단 하나만을 가지는 간단한 인터페이스입니다.

profile
작성자 개인이 잊을 때마다 보라고 정리한 글

0개의 댓글