[OS] Thread

Shef·2022년 4월 4일
1
post-thumbnail

쓰레드의 이해


쓰레드는 어떠한 배경에서 등장했을까?

과거에는 두 가지 이상의 일을 동시에 처리하기 위해서, 혹은 둘 이상의 실행 흐름을 처리하기 위해서 하나의 프로그램으로부터 둘 이상의 프로세스를 생성하는 일이 많았다고 한다.

예를 들어 과거에는 여러 서버 프로세스를 만들어 클라이언트로부터의 요청을 동시에 처리하곤 했다.

서로 별개의 프로그램을 위해서는 어쩔 수 없는 일이지만 하나의 프로그램이 둘 이상의 프로세스 생성을 요구하는 것은 부담스러운 일이다.

왜냐하면 프로세스가 많아질수록 컨텍스트 스위칭이 많아지고 프로세스의 생성 또한 오랜 시간이 걸리기 때문이다.

위와 같은 문제를 해결하기 위해 쓰레드가 등장하였다.

  • 프로세스란?
    현재 실행중인 프로그램. 하나의 프로그램은 여러 개의 프로세스를 가질 수 있다.

  • 컨텍스트 스위칭이란?
    프로세스 혹은 쓰레드가 다른 프로세스 혹은 다른 쓰레드로 스케쥴링 될 때
    현재까지의 상태(혹은 문맥)를 저장하고 다시 돌아왔을 때 이 상태를 복원하는 작업이다.

쓰레드란 무엇일까?

쓰레드란 프로세스 내에서 실행되는 흐름 중 하나를 말한다.

메모리 구조 관점에서 볼 때 프로세스는 서로 완전히 다르다.
따라서 컨텍스트 스위칭 시 많은 컨텍스트 정보를 저장하고 복원해야 한다.

반면에 쓰레드는 code 영역 data 영역 heap 영역을 공유한다.

따라서 쓰레드간 컨텍스트 스위칭 시 보다 적은 정보(메모리 관련 정보를 저장할 필요 없음)를 저장하고 복원하기 때문에 프로세스 간 컨텍스트 스위칭보다 적은 시간이 소요된다.

일반적으로 프로그램은 하나의 쓰레드를 갖고 있고, 둘 이상의 쓰레드를 가진 프로세스를 멀티쓰레드 프로세스라고 한다.

출처 : 위키백과 - 스레드

멀티 쓰레드 방식은 언제 사용할까?

  1. 어떤 일이 동시에 처리되야 할 경우

    예를 들어 싱글 쓰레드 방식의 서버 프로그램이 있다고 하자.

    사용자가 요청을 한 경우 하나의 쓰레드가 맡아서 요청을 처리해야 한다.

    요청을 처리하는 중에 다른 사용자가 또 요청을 하는 경우 이 요청이 완료되기까지 기다려야 할 것이다.

    멀티쓰레드라면 각 요청을 각 쓰레드가 하나씩 맡아서 동시에 요청을 처리할 수 있다.


  2. 어떤 일을 빠르게 처리하고 싶은 경우

    예를 들어 1부터 100까지 더하는 작업이 있고 더하기 연산을 하는데 1초가 걸린다고 가정해보자.

    싱글 쓰레드의 경우 1부터 100까지 더하는데 100초가 걸린다.

    쓰레드를 4개 만들어서 작업을 각각 1/4씩 나누어서 처리한 후 모두 더해주면 약 25초가 걸린다.

  • 쓰레드가 많으면 무조건 작업을 빨리 처리할까?
    쓰레드가 많아도 코어가 쓰레드의 개수보다 적다면 컨텍스트 스위칭을 하며 작업을 처리해야 하고, 컨텍스트 스위칭에는 시간이 소요 되기 때문에 오히려 느릴 수도 있다.

OS의 스케쥴링과 쓰레드의 관계는 어떻게 될까?

대부분 최신 운영체제에서 스케줄 되는 대상은 프로세스가 아니라 쓰레드이다.

프로세스 간 컨텍스트 스위칭은 어떤 프로세스에 있는 쓰레드에서 다른 프로세스에 있는 쓰레드로 스케쥴링 될 때를 의미한다.

CPU 코어 개수와 쓰레드 개수는 무슨 상관이 있을까?

CPU 코어의 개수에 따라서 병렬적으로 실행할 수 있는 쓰레드의 개수가 정해진다.

예를 들어 CPU 코어가 4개이고 쓰레드 또한 4개라면 이 쓰레드들은 모두 병렬적으로 실행이 가능하다.

그러나 CPU 코어가 1개이고 쓰레드가 4개라면 이 쓰레드들은 CPU 코어 하나가 빠르게 왔다 갔다 하면서 처리하기 때문에 병렬적으로 실행되는 것처럼 보여도 실은 병렬적이지 않다.

한 편 '하이퍼쓰레드'라는 기술은 운영체제에게 코어 하나가 여러 개로 인식되게끔 할 수 있다.

이 기술은 코어 하나가 어떤 쓰레드에 대한 작업 중 메모리 스톨 때문에 비어버린 시간을 다른 쓰레드에 할당하는 기술이다.

따라서 8코어 CPU가 ‘하이퍼쓰레드’ 기술에 의해 16코어처럼 운영체제에 인식되더라도 병렬적으로 실행할 수 있는 쓰레드는 역시 8개라고 할 수 있다.

  • 메모리 스톨(memory stall)이란?
    CPU 작업 중 메모리로부터 데이터를 기다리는 시간

쓰레드는 어떤 과정을 거쳐 만들어질까?

자바의 경우 쓰레드를 만들기 위해서 다음과 같은 방식으로 코드를 작성해야 한다.

    class MyThread extends Thread{
    	public void run() { /* 작업내용 */} //Thrad클래스의 run()을 오버라이딩
    }

    class Th1{
    	public void main(String args[]){
    		MyThread t1 = new MyThread();
    		t1.start();
    	}
    }
    

위와 같이 작성된 코드에서 t1 객체의 start()가 호출되면 다음과 같은 일이 일어난다.

  1. 프로세스의 스택 영역에 쓰레드의 스택 공간을 만든다.

  2. 쓰레드의 정보를 저장할 TCB를 만들어 커널 영역에 보관한다.

  3. OS의 스케쥴링 큐에 TCB에 대한 포인터를 넣는다.
    (Operation System Concepts 123p를 보면 스케쥴링 큐에 PCB의 포인터를 넣는다고 나와 있다. 한 편 실제로 스케쥴링되는 단위는 쓰레드이고, TCB는 PCB에 대한 포인터를 갖고 있기 때문에 스케쥴링 큐에 TCB에 대한 포인터가 넣어진다고 러프하게 이해할 수 있을 것 같다.)

  4. 만들어진 쓰레드를 OS가 스케쥴링 했을 때 스케쥴링 큐에 넣어진 TCB에 따라 CPU의 문맥이 업데이트 된 후 쓰레드가 실행이 된다.

  • PCB(Process Control Block)란?
    프로세스의 문맥을 저장하는 자료 구조.

    다음과 같은 정보를 저장한다.

    1. 실행 상태 : 프로세서 레지스터, 프로그램 카운터, 스택 포인터
    2. 스케줄링 큐용 다양한 포인터
    3. 메모리 관련 정보 : 페이지 테이블의 주소를 보관하는 레지스터
    4. 프로세스에 존재하는 쓰레드들의 TCB리스트

  • TCB(Thread Control Block)란?
    쓰레드의 문맥을 저장하는 자료 구조.

    다음과 같은 정보를 저장한다.

    1. 실행 상태 : 프로세서 레지스터, 프로그램 카운터, 스택 포인터
    2. 스케줄링 큐용 다양한 포인터
    3. 해당 쓰레드를 포함하는 프로세스의 PCB를 포함하는 포인터

참고 자료

Abraham Silberschatz 외 2명, 운영체제, 박민규, 1쇄, 퍼스트 북, 3,4,5장, 2020
구현회, 그림으로 배우는 구조와 원리 운영체제, 6쇄, 한빛아카데미, 3장, 2021
윤성우, 뇌를 자극하는 윈도우즈 시스템 프로그래밍, 10쇄, 한빛미디어, 11장, 2021
남궁 성, 자바의 정석 3rd Edition, 1판 2쇄, 도우출판, 13장, 2016

0개의 댓글