[CS 스터디] 운영체제 5일차 - Thread

강아람·2022년 12월 31일
0

운영체제

목록 보기
5/11
post-thumbnail

📚 Thread(스레드)

프로세스 내에서 실행되는 흐름의 단위 또는 CPU 스케줄링의 기본단위

Thread가 필요한 이유

자원의 효율성

  • 프로세스가 자원을 할당받으면 프로세스의 스레드들이 그 자원을 공유하며 사용할 수 있음
  • 프로세스를 생성하기 위한 시스템 콜이 줄어듦

오버헤드 감소

스레드는 프로세스의 메모리 영역(data, code, heap 영역)을 공유하기 때문에 프로세스의 Context Switching에 비해 효율적임


Thread의 메모리 구조

  • 스레드는 고유한 ID, 프로그램 카운터(PC), 레지스터(register) 집합, 스택을 가짐
    • Thread ID : 스레드를 구분하기 위한 고유 ID
    • Program Counter : 스레드마다 독립적인 실행흐름을 가지기 때문에 고유한 PC를 가짐
    • Register : 스레드의 상태 등에 대한 정보를 저장하기 위해 고유한 Register Set을 가짐
  • 스레드는 프로세스 내에서 Code, Data, Heap 영역을 공유하고 Stack 영역만 할당받음
    • Stack : 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소값, 함수 내에서 선언된 변수 등을 저장하기 위해 사용되는 메모리 공간이다. 스레드는 독립적인 함수 호출이 가능하기 때문에 고유한 스택을 할당받아야 한다.
  • 동일한 프로세스 내에 존재하는 스레드 간에는 동일한 자원에 대해 읽고 쓰는 것이 가능

TCB (Thread Control Block)

  • 스레드 별로 존재하는 자료구조로, 프로그램 카운터(PC)와 레지스터 집합(CPU 정보), PCB, 상태정보, 프로세스 주소를 가리키는 포인터
  • PCB에는 해당 프로세스의 TCB 리스트를 저장하고, 각각의 TCB는 PCB의 주소값을 가지고 있음
  • 같은 프로세스 내 Context Switching(스레드 간)이 발생하면 TCB 정보만 저장
  • 다른 프로세스 간 Context Switching(프로세스 간)이 발생하면 PCB, TCB 정보 저장
    • 프로세스 A의 스레드 A 실행 중 프로세스 B의 스레드 B가 CPU를 선점하면 현재 PC 값을 스레드 A의 TCB에 저장하고, 스레드 B의 TCB에 있는 PC 값을 불러와 CPU의 PC register에 저장하고 스레드 B를 실행한다.



📚 Thread의 종류

Single Thread와 Multi Thread

Single Thread

프로세스를 하나의 스레드로만 실행
▶ 하나의 레지스터와 스택으로 표현이 가능하다.

장점

1) Context Switching 작업을 요구하지 않는다.
Context Switching은 여러 개의 프로세스가 하나의 프로세서(CPU)를 공유할 때 발생하는 작업으로 많은 비용을 필요로 한다.

2) 자원 접근에 대한 동기화를 신경쓰지 않아도 된다.
여러 개의 스레드가 프로세스의 자원을 공유할 경우, 공유 자원에 대한 접근 제어가 필요하다.

3) 단순한 작업 시에는 싱글 스레드 프로그래밍이 더 효율적이다.
만약 CPU 사용하는 작업으로만 구성된 프로세스의 경우라면 두 개의 스레드 실행으로 인한 Context Switching 비용이 발생하기 때문에 하나의 스레드 작업이 더 효율적일 수 있다.

4) 프로그래밍 난이도가 쉽고, CPU와 메모리를 적게 사용한다. (비용이 적게 든다.)
멀티 스레드 프로그래밍 구현을 위해 자원 공유 방법 등 복잡한 작업이 필요하고, 스레드 개수만큼 자원을 할당하게 된다.


단점

1) 여러 개의 CPU를 활용하지 못한다.
프로세스를 하나의 스레드로만 실행하기 때문에 여러 개의 CPU가 존재하더라도 효율적으로 사용하지 못한다. (내 생각...)

2) 연산량이 많은 작업을 실행하는 경우, 그 작업이 완료되어야 다음 작업을 수행할 수 있다.
3초를 기다려야 하는 작업 이후 사용자의 화면에 작업 결과가 반영되는 경우 사용자는 3초 동안 다른 버튼을 클릭하지 않고 결과를 기다려야 한다.

3) 싱글 스레드 모델은 에러 처리를 못하는 경우 정지한다.


Multi Thread

프로세스를 다수의 스레드로 실행
▶ 각각의 스레드가 고유의 레지스터와 스택으로 표현되며, 프로세스 내에서 자원을 공유하여 자원 생성과 관리 중복 최소화가 가능하다.

장점

1) 메모리 공간과 시스템 자원 소모가 줄어든다.

  • 프로세스 내의 자원을 여러 개의 스레드가 공유하기 때문에 메모리 공간을 적게 할당할 수 있고, 쉽게 데이터를 주고받을 수 있다.
  • 프로세스 간 문맥 교환과 달리 스레드 간 문맥 교환에서는 캐시 메모리를 초기화하지 않기 때문에 더 빠르다. 따라서 CPU의 유휴 시간이 줄어든다.

Cache Reset Cost

프로세스 간에는 공유하는 데이터가 없으므로 캐시가 지금껏 쌓아놓은 데이터들이 무너지고 새로 캐시정보를 쌓아야 한다. 이것이 프로세스 문맥 교환에 부담이 되는 요소이다.
반면, 스레드라면 저장된 캐시 데이터는 스레드가 바뀌어도 공유하는 데이터(code, data, heap영역)가 있으므로 의미있다. 그러므로 스레드의 문맥 교환 속도가 더 빠른 것이다.

2) 사용자에 대한 응답성이 증가한다.
프로세스의 일부(스레드 중 하나)가 중단되거나 긴 작업 수행 중에도 프로세스 수행이 계속 된다. 즉, 에러가 발생하면 새로운 스레드를 생성하여 극복할 수 있다. 또한 여러 스레드가 존재하기 때문에 오래 걸리는 작업이 실행되는 도중에 사용자와 인터렉션이 가능하다.

3) 멀티 프로세서의 활용도가
높다.

멀티 스레드 프로그래밍 구조에서 각각의 스레드가 다른 프로세서에 의해 병렬로 실행 가능하므로 병렬성이 증가한다.


단점

1) 싱글 스레드보다 더 많은 비용이 소모된다.
문맥교환, 동기화 등으로 인해 스레드 생성의 오버헤드가 발생하기 때문에 단일 스레드보다 느리고, 스레드마다 스택 등 메모리 할당이 필요하다.

2) 공유 자원에 대한 동기화 처리가 필요하다.
프로세스 내의 스레드들은 프로세스의 자원(데이터, 힙 영역)을 공유하기 때문에 뮤텍스, 세마포어 등의 동기화 방법을 생각해야 한다.

3) 프로그래밍 난이도가 높고, 자원 소모가 더 크다.



User Thread와 Kernel Thread

스레드 지원(생성) 주체에 따라 유저 레벨 스레드와 커널 레벨 스레드로 구분된다.

User Thread (사용자 레벨 스레드)

  • 유저 영역의 라이브러리를 통해 구현되며, 해당 라이브러리는 스레드 생성 및 스케줄링 등에 관한 관리 기능 제공
  • 동일한 메모리 여역에서 스레드가 생성 및 관리되기 때문에 속도가 빠름
  • 여러 개의 사용자 스레드 중 하나가 중단되면 나머지 스레드도 모두 중단됨 (커널이 스레드를 인식하지 못해 프로세스 자체를 대기 상태로 전환 시킴)
  • 스레드 정보(TCB)는 프로세스 내에서, 프로세스 정보(PCB)는 커널에서 관리

장점

1) 이식성이 높다.
커널에 독립적으로 스케줄링(프로세스 내에서 스케줄링) 할 수 있기 때문에 모든 운영체제에 적용할 수 있다.

2) Context Switching으로 인한 비용(오버헤드)이 적다.
스케줄링 또는 동기화를 위한 시스템 콜을 하지 않기 때문이다.

3) 유연한 스케줄링이 가능하다.
커널이 아닌 스레드 라이브러리가 스레드 스케줄링을 하기 때문에 응용 프로그램에 맞게 스케줄링을 할 수 있다.


단점

1) 시스템의 동시성을 지원하지 않는다.
프로세스 단위로 프로세서를 할당하여 스레드 단위로 다중 처리가 불가능하다. 프로세스 내의 스레드가 대기 상태가 되면 다른 스레드 작업도 중지된다.

2) 확장에 제약이 있다.
커널이 한 프로세스에 속한 여러 스레드에 프로세서를 동시에 할당할 수 없어 다중 처리 시스템에서 규모를 확장하기 어렵다.

3) 스레드 간 보호가 불가능하다.
스레드 라이브러리에서 스레드 간 보호를 제공해야 프로세스 수준에서 보호가 가능하다.


Kernel Thread (커널 레벨 스레드)

사용자 레벨 스레드의 한계를 극복하는 방법으로, 커널이 스레드와 관련된 모든 작업을 관리한다.

  • 운영체제가 지원하는 스레드 기능을 통해 구현되며, 커널이 스레드 생성 및 스케줄링 등에 관한 관리
  • 하나의 스레드가 시스템 콜 등으로 인해 중단되더라도, 커널은 프로세스 내의 다른 스레드를 중단시키지 않고 계속 실행 (멀티 프로세싱 환경에서 커널이 여러 개의 스레드를 각각 다른 프로세서에 할당 가능)
  • 사용자 레벨 스레드에 비해 생성 및 관리가 느림
  • 커널이 전체 TCB와 PCB를 관리

장점

프로세스 내 스레드의 병렬 실행이 가능하다.
커널이 프로세스 내의 각 스레드를 개별적으로 관리하기 때문에 하나의 스레드가 block 상태(system call)가 되어도, 다른 스레드들은 계속 작업을 수행할 수 있다.

단점

Context Switching 등에 의한 부하(Overload)가 크다.
커널 영역에서 스레드의 생성과 관리가 수행되기 때문에 모드 전환이 빈번하며, 모드 전환 시 Context Switching이 발생하기 때문에 부하가 크다.


추가로 공부할 내용

  • 다중 스레드 모델
  • 혼합된 스레드 모델
  • Scheduler Activation


📚 JAVA Thread State Transition (스레드 상태 전이)



📚 Process와 Thread의 비교

Process와 Thread의 차이점

Process

모든 프로그램은 운영체제로부터 실행되기 위한 메모리 공간을 할당받아야 실행될 수 있는데, 이 메모리를 할당받은 동적 상태가 프로세스이다. 즉, 프로세스란 실행되고 있는 컴퓨터 프로그램을 의미한다.

Thread

하나의 프로그램을 여러 개의 프로세스로 나누어 실행하기 위해서는 프로세스마다 메모리 영역의 할당이 필요하고, 통신 방법에 제약이 있다. 이러한 프로세스의 한계를 극복하기 위해 더 작은 실행 단위인 스레드라는 개념을 도입하였다. 즉, 스레드는 프로세스의 최소 실행 흐름 단위를 의미한다.
스레드는 프로세스의 자원을 공유하기 때문에 메모리 절약이 가능하고, 통신이 쉽다.

🌟 가장 중요한 차이점!

프로세스는 각각 독립된 메모리 영역(Code, Data, Heap, Stack)을 할당받지만, 스레드는 프로세스 내의 Code, Data, Heap 영역을 공유하고 Stack만 고유하게 할당받는다.

만약, 멀티 프로세스 구조에서 하나의 프로세스에 에러가 발생한다면 어떻게 될까?

에러가 발생해도 프로세스는 독립적인 메모리 영역을 가지고 있기 때문에 공유하고 있는 파일 등이 손상되지 않는다면 다른 프로세스에 영향을 주지 않는다.

그렇다면 멀티 스레드 구조에서 하나의 스레드에 에러가 발생한다면 어떻게 될까?

스레드는 속해있는 프로세스의 메모리 영역을 공유하고 있기 때문에 하나의 스레드에 에러가 발생해 종료된다면 다른 스레드에도 영향을 주어 모든 스레드가 종료된다.

🌟 운영체제 관점에서 스레드가 프로세스의 자원을 공유하는 이유

CPU의 최소 작업 단위는 스레드이다. 그래서 CPU의 스케줄링 단위 또한 스레드가 된다. 그러나 운영체제의 최소 작업 단위는 프로세스이다. 그렇기 때문에 운영체제는 프로세스에 메모리 영역을 할당하고, 프로세스에 할당된 메모리 영역을 스레드들이 공유하게 된다.



프로그래밍 방법

Multi Programming

하나의 프로세서(CPU)가 하나의 프로세스를 수행하는 동안 다른 프로세스에 접근할 수 있도록 하는 프로그래밍 방법이다.
하나의 프로세서가 하나의 프로세스를 처리하는 과정에서 프로세스의 입출력 처리가 완료될 때까지 프로세서가 대기하는 시간을 줄이기 위해 사용한다. (효율적인 CPU 사용)

Multi Tasking

다수의 작업(프로세스 또는 스레드)을 운영체제의 스케줄링에 의해 번갈아 가며 수행할 수 있는 프로그래밍 방법이다. 프로세서는 특정 시점에 하나의 작업만 수행할 수 있는데 사용자가 느끼지 못할 정도로 빠르게 작업들을 번갈아가며 수행하여 동시에 수행되는 것처럼 느껴지게 한다.

Multi Processing

2개 이상의 프로세서(core, CPU)를 사용하여 여러 개의 프로세스를 동시에 실행할 수 있는 환경이다. 즉, 멀티 프로세싱이란 하나의 작업(프로그램)이 다수의 프로세서에 의해 처리되는 환경이다.

Multi Process

하나의 프로그램(작업)을 여러 개의 프로세스로 나누어 병렬로 처리하는 프로그래밍 방법이다.

Multi Thread

Multi Tasking이 하나의 운영체젱 안에서 여러 프로세스가 실행되는 것이라면, Multi Thread는 하나의 프로세스가 여러 스레드를 통해 여러 개의 작업을 나누어 동시에 처리하는 것을 의미한다. (동시에???는 멀티 코어일 경우가 아닐까요?)



Process와 Thread의 Context Switching 차이점

Context란?

번역하면 "문맥"이라는 뜻이지만 프로그래밍에서는 작업의 집합(프로세스 또는 스레드의 집합)을 관리, 실행하는 최소한의 정보를 포함하는 객체를 말한다.
쉽게 이야기하면 작업들의 현재 상태에 대한 정보를 포함하는 객체이다.

🌟 Context Switching이란?

CPU 스케줄링에 의해 현재 실행되고 있는 Context를 잠시 중단하고 다른 Context를 실행하는 것이다.

그렇다면 Process와 Thread의 Context Switching에는 어떤 차이가 있을까?

Process의 Context Switching
프로세스 A가 CPU를 할당받아 작업을 하다가 할당된 시간을 다 써서 프로세스 B에게 CPU를 넘겨줘야 하는 상황에서 발생한다.
이 경우, 현재 CPU의 PC register에 있는 정보가 프로세스 A의 PCB(Process Control Block)에 기록된 후 프로세스 B에게 CPU의 제어권이 넘어간다. 그리고 프로세스 B의 실행 정보가 PC register에 저장된다.
만약 프로세스들이 여러 개의 thread로 나누어져 있다면 TCB(Thread Control Block)의 정보도 바꾸어야 한다.

TCB와 PCB는 커널에 있고 switching 작업은 커널이 하는거라 CPU는 실제로 일하지 않고 놀고 있겠죠? 이 시간을 유휴 시간, 실제로 사용하지 않는 시간이라고 해요. 유휴 시간이 길수록 CPU 효율은 떨어져요.

프로세스 A의 스레드 A가 I/O 작업을 위해 스레드 B에게 CPU 제어권을 넘길 때에도 Context switching이 발생하는데 스레드 간 Context Switching 시에는 TCB 정보만 변경하면 된다.

즉, 간단히 말하면 Process의 Context Switching은 독립적인 프로세스 정보를 모두 반영해야 할 뿐만 아니라 캐시 메모리도 비워야 하기 때문에 비용이 많이 들고 CPU의 효율도 떨어진다.
이에 비해 Thread의 Context Switching은 스레드가 프로세스 내의 자원을 공유하기 때문에 독립적인 메모리 영역인 stack 주소만 바꿔주면 되기 때문에 훨씬 비용이 적다!



추가로 공부할 내용

  • 동시성과 병렬성

0개의 댓글