Thread(스레드)
이번 포스팅에서는 스레드에 대해 알아보도록 하겠습니다. 스레드는 동시 작업, 동기, 비동기 처리 등 실제로 많이 쓰이는 개념이므로 알아두시면 참 좋을 거라고 생각합니다.
Thread란
Light Weight Process(LWP)라고 불리는 Thread는 가벼운 프로세스로, 자원은 공유하고 제어 부분만 가지고 있기 때문에 일반 프로세스보다 가볍습니다. 제어 요소와 코드만을 가지고 있으며, 데이터와 자원들은 동일 프로세스 내의 다른 Thread들과 공유합니다.
프로세서(CPU) 활용의 기본 단위로, 스레드가 여러 개 있으면 각각의 프로세서를 활용할 수도 있게 됩니다.
프로세스를 자원과 제어로 나눌 수 있다면, Thread는 제어만 있다고 생각하면 됩니다. 프로세스는 자원을 할당받고 제어까지 하지만 Thread는 프로세스가 할당받은 자원은 다른 Thread와 공유해 사용하므로 제어부 분만 담당하고 있습니다.
Thread의 구성 요소는 다음과 같습니다.
- Thread ID : 스레드 식별 번호
- Register set(program counter, stack pointer 등) : 레지스터 정보
- Stack(local data) : 함수 호출 정보, 지역변수, for문 내의 지역변수 등의 지역적인 데이터
- 현재 상태
같은 프로세스의 스레드들은 동일한 주소 공간을 공유합니다. 각각의 스레드는 동일한 프로세스의 메모리 공간 내에 각각의 스택 영역을 가지고 있습니다. 또한 각 스레드들의 제어 정보는 코드 영역에 저장됩니다.
Thread가 다른 Thread와 공유하는 부분
- code section
- data section
- OS resource
Multi Thread
프로세스는 하나의 Thread를 사용할 수도 있으며, 여러 개의 Thread를 사용할 수도 있습니다. 하나의 Thread를 사용하는 것을 Single Thread, 여러 개의 Thread를 사용하는 것을 Multi Thread라고 합니다.
같은 프로세스를 여러 개 수행하면 메모리에 각각의 프로세스가 따로 올라가게 됩니다. 이런 경우 메모리 공간의 사용에 있어서, 그리고 자원도 따로따로 할당받아 비효율적인 프로그램이 됩니다.
또한, 프로세스 사이의 Context Switching은 오버헤드가 매우 큰 작업인데 비해, 동일한 프로세스 내에서 Thread가 바뀌는 건 그에 비해 오버헤드가 적어 효율적입니다.
멀티 스레드로 구성된 구조에서는 하나의 스레드가 blocked 상태인 동안에도 동일한 프로세스 내의 다른 스레드가 실행(running)되어 빠른 처리를 할 수 있습니다.
멀티 스레드를 사용하면 동일한 일을 수행하는 다중 스레드가 협력하여 높은 처리율과 성능 향상, 그리고 병렬성을 높일 수 있습니다.
스레드 장점
- 응답성(Responsiveness)
- 일부 스레드의 처리가 지연되어도, 다른 스레드는 작업을 계속 처리할 수 있습니다.
- 단일 스레드로 작성된 프로세스는 I/O 작업이 지연되면 이후 작업 수행이 멈춰 늦어집니다.
- 멀티 스레드로 수행하면 입출력을 요구한 스레드가 block이 되어도 다른 스레드는 계속 작업을 수행합니다.
- 자원 공유(Resource Sharing)
- 자원을 공유해서 효율성이 증가됩니다.(커널의 개입을 피할 수 있습니다.)
- 멀티 스레드로 구성하면 자원을 공유하기 때문에 보다 적은 Context Switching으로 동시에 작업할 수 있습니다.
- 경제성(Economy)
- 프로세스의 생성, Context Switch에 비해 효율적입니다.
- Utilization of MP Architectures(병렬 처리)
- 스레드가 여러 개면 여러 개의 프로세스를 동시에 사용할 수 있습니다.
- 병렬 처리를 통해 성능이 향상됩니다.
스레드 구현(사용자 수준, 커널 수준)
스레드를 구현하는 방식에는 크게 사용자 스레드, 커널 스레드 두 가지가 있습니다.
사용자 수준 스레드
- 사용자 영역의 라이브러리를 이용해 구현하는 스레드입니다.
- 스레드 생성, 스케줄링 라이브러리 등
- POSIX threads, Win32 threads, Java thread API 등
- 커널은 스레드의 존재를 모릅니다.
- 커널의 관리(개입)를 받지 않습니다. 따라서 스레드 생성 및 관리의 부하가 적으며, 유연한 관리가 가능하고, 다른 OS로의 이식성이 높습니다.
- 커널은 프로세스 단위로 자원을 할당합니다.
- 따라서, 사용자 수준 스레드는 하나의 스레드가 block상태가 되면, 모든 스레드가 대기하게 됩니다.
커널 수준 스레드
- 커널이 직접 관리합니다. 커널 영역에서 스레드의 생성과 관리를 수행합니다.
- Context Switching 등의 부하(Overhead)가 큽니다.
- 커널이 각 스레드를 개별적으로 관리합니다.
- 프로세스 내 스레드들의 병행 수행이 가능합니다.
- 즉, 하나의 스레드가 block상태가 되어도 다른 스레드는 계속 작업을 수행할 수 있습니다.
멀티 쓰레딩 모델
- 다대일(n:1) 모델 : 사용자 수준 스레드
- 일대일(1:1) 모델 : 커널 수준 스레드
- 다대다(n:m) 모델 : 혼합형 스레드
- n(사용자 수준) > m(커널 수준)
혼합형 스레드
n개의 사용자 수준 스레드 : m개의 커널 수준 스레드( n > m)
사용자는 원하는 수만큼의 스레드를 사용할 수 있습니다. 커널 스레드는 자신에게 할당된 하나의 스레드가 block 상태가 되어도, 다른 스레드를 수행할 수 있습니다.(병행처리 가능)
효율적이면서도 유연한 방식이 혼합형 스레드입니다.
정리
- Thread란?
- 프로세서 사용의 기본 단위
- 자원을 제외한 제어만을 담당
- 다른 Thread와 자원을 공유
- 각각의 Thread가 다른 프로세서를 동시에 활용할 수 있음
- Multi-Thread
- 하나의 프로세스가 여러 개의 Thread를 사용하는 것
- Thread의 장점
- 응답성
- 자원 공유
- 경제성
- 병렬 처리
- Thread의 구현
- 사용자 수준 Thread
- 커널 수준 Thread
- Thread 모델
- 다대일(n:1) 모델 : 사용자 수준 Thread
- 일대일(1:1) 모델 : 커널 수준 Thread 한 개 당 사용자 수준 Thread 한 개
- 다대다(n:m) 모델(혼합형 모델) : n개의 사용자 수준 스레드 : m개의 커널 수준 스레드( n > m)
마치며
이번 포스팅도 스스로 많이 부족하단 생각이 들었습니다. 글을 쓰는 것, 타인에게 설명하는 것이 정말 어려운 거 같습니다.
이번 포스팅을 보셨다면, 스레드에 대해 더 찾아서 공부해보시거나, 동기/비동기(sync/async), 블락/언블락(blocked/unblocked)에 대한 주제를 검색해 개념을 공부해 보시는 것을 추천드립니다.
다음 포스팅은 프로세스 스케줄링에 대한 내용을 다룰 거 같습니다. 이번 글에 대해 궁금한 점이나, 부족한 점, 잘못된 점 댓글로 적어주시면 감사하겠습니다. 읽어주셔서 감사합니다.