스레드(Thread)
•
스레드는 CPU에 작업을 요청하는 실행 단위를 말하며, 프로세스 내에서 실행되는 프로그램 코드의 흐름을 말한다.
•
프로세스 생성 과정을 보면 운영체제는 프로그램을 실행시키기 위해 프로그램의 코드와 데이터를 메모리에서 가져오고, PCB 생성 및 메모리 확보 후 준비된 프로세스를 준비 큐에 삽입한다. 이렇게 프로세스가 생성되면 CPU는 스케줄링에 맞춰 작업을 수행하는데, CPU 스케줄링에 의해 CPU가 받게 되는 작업을 스레드라 부른다.
•
운영체제의 입장에서 작업의 단위는 프로세스지만, CPU 입장에서는 스레드가 된다.
•
C나 C++, Java와 같은 프로그래밍 언어에서 main() 함수(메서드)를 실행하면서 메인 스레드가 실행되고, return이나 함수의 끝을 만나게되면 메인 스레드가 종료되게 된다. 멀티스레드 어플리케이션이라면 스레드가 모두 종료될 때까지 프로세스는 종료되지 않는다.
•
각 스레드는 각각 독립된 스레드 ID, 프로그램 카운터(PC), 레지스터 집합과 메모리의 스택 영역을 가진다.
•
하나의 프로세스에 여러 스레드가 있는 경우, 프로세스의 메모리 구조는 아래와 같다.
프로세스와 차이점
•
운영체제마다 다르지만 프로세스를 수행할 때 최소 32~64MB의 메모리를 사용하는데, 스레드는 1MB 이내의 메모리만 사용한다. 이러한 이유로 스레드를 경량 프로세스라고 부르기도 한다.
•
프로세스는 새로 생성될 때 부모의 프로세스에서 메모리를 복사해서 생성되는데 비해, 스레드는 하나의 프로세스 내에서 스택 영역만 새로 생기고 힙과 데이터 영역은 공유하기 때문에 Context Switching 오버헤드가 적다.
•
프로세스 간 통신은 IPC를 통해서만 가능하지만, 스레드는 공유 메모리를 통해 데이터를 교환할 수 있다.
•
각 프로세스는 독립된 메모리를 사용하기 때문에 다른 프로세스에 영향을 받지 않지만, 스레드는 자원을 공유하기 때문에 동기화 문제가 발생할 수 있다.
•
하나의 스레드에서 발생한 문제가 프로세스 전체에 영향을 미칠 수 있다.
스레드 유형
•
커널 수준 스레드(1:1 매핑 방식)
◦
OS(커널)가 스레드 생성, 스케줄링 등 스레드를 직접 관리하는 구조
◦
커널이 각 스레드를 개별적으로 관리하기 때문에, 프로세스 내의 스레드들이 병렬적으로 수행 가능하다.
◦
하나의 스레드가 block 되어도 다른 스레드에서는 계속 작업이 가능하다.
◦
커널 영역에서 스레드의 생성과 관리를하기 때문에 사용자 스레드보다 속도가 느리다.
◦
Context Swtiching으로 인한 오버헤드가 크다.
•
사용자 수준 스레드(N:1 매핑 방식)
◦
사용자 영역의 스레드 라이브러리를 통해 구현하여, 라이브러리에 의해 스레드 생성과 스케줄링을 관리하는 구조
◦
커널은 스레드의 존재를 인식하지 못하기 때문에 커널의 개입을 받지 않고, 그로 인해 스레드의 생성과 관리의 부하가 적다.
◦
동일한 메모리 영역에서 스레드가 생성되고 관리되므로 커널 스레드보다 빠른다.
◦
라이브러리를 통해 구현하기 때문에, 이식성이 높다
◦
커널이 프로세스 단위로 자원을 할당하기 때문에 하나의 스레드가 block 된다면 모든 스레드가 대기해야 한다.
•
혼합 스레드(N:M 매핑 방식)
◦
커널 수준 스레드와 사용자 수준 스레드가 혼합된 구조로, 1:1 방식과 N:1 방식의 문제점을 해결하기 위한 구조
◦
프로세스 내 스레드들이 병렬적으로 수행 가능하다.
◦
사용자가 원하는 수만큼의 스레드를 사용할 수 있기 때문에, 효율적이고 유연하게 구조를 설계할 수 있다.
◦
스레드 풀링 기법을 통해 1:1 방식의 스레드 매핑에서 오버헤드를 줄인다.
스레드 풀링
시스템이 관리하는 스레드 풀을 응용 프로그램에 제공하여 스레드를 효율적으로 사용할 수 있게 만든 방법으로, 미리 생성된 스레드를 재사용하여 스레드 생성 시간을 줄이고 시스템 부하를 낮춘다. 또한 동시 생성할 수 있는 최대 스레드 수를 제한하여 시스템의 자원 소비를 줄이고 응용 프로그램의 성능을 일정 수준으로 유지할 수 있다.