스레드(Thread) 알아보기
스레드(Thread)란 프로세스 내에서 실행되는 흐름의 단위를 말합니다.
일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있습니다.
이러한 실행 방식을 멀티스레드(multi-thread)라고 합니다.
그림을 보면 스레드는 자신만의 고유한 스레드 ID, 프로그램 카운터(PC), 레지스터 집합, 스택을 가지고 코드 , 데이터 및 OS 리소스(예 : 열린 파일 및 신호)는 프로세스 내의 다른 스레드와 공유합니다.
스레드마다 고유한 자원(PC, 레지스터 집합, 스택)을 가지고 있는 이유는 독립적인 함수 호출을 가능하게 하여 독립적인 실행 흐름을 추가하기 위해서입니다.
프로세스 vs 스레드 주요 차이점
프로세스와 스레드의 주요 차이점은 동일한 프로세스 내의 스레드는 공유 메모리 공간에서 실행되는 반면 프로세스는 별도의 메모리 공간에서 실행된다는 점입니다.
스레드 장단점
장점
- 사용자 응답성 증가
- 프로세스가 여러 스레드로 분할된 경우 일부 스레드의 처리가 지연되어도, 다른 스레드는 작업을 계속 처리가 가능합니다.
- 다중 처리로 성능 향상
- 단일 프로세스에 다중 스레드가 있는 경우 다중 프로세서에서 다중 스레드를 예약할 수 있습니다. 이렇게 하면 프로세스 성능을 향상할 수 있습니다.
- 경제성이 좋음
- 스레드는 한 프로세스 내에서 자원(코드, 데이터, 힙)을 공유하기 때문에 프로세스에 비해 자원 할당 비용이 적게 들고 문맥 교환(context switch) 비용도 적게 듭니다.
- 통신이 쉬움
- 프로세스 간 통신은 특정 통신 기법(IPC)이 필요하지만, 스레드는 공유(데이터, 힙) 주소 공간을 사용하면 되기 때문에 데이터 교환에서는 특별한 기법이 필요 없습니다.
단점
- 자원을 공유하기 때문에 타 스레드 메모리 공간을 덮어쓸 수 있어 안정성에 다소 취약합니다.
스레드 종류
스레드는 운영체제에 따라 다양하게 구현할 수 있는데, 대부분 다음 세 가지 형태로 구현합니다.
- 사용자 수준 스레드
- 커널 수준 스레드
- 혼합 스레드
사용자 수준 스레드 (User-Level Thread)
사용자 스레드는 커널 영역의 상위에서 지원되며 일반적으로 사용자 수준의 라이브러리를 통해 구현됩니다.
이 경우 커널은 스레드의 존재를 인식하지 못하기 때문에 커널의 개입을 받지 않습니다.
다수의 사용자 수준 스레드가 커널 수준 스레드 한개에 매핑되므로 다대일(n:1)
스레드 매핑이라고 합니다.
장점
- 사용자 영역에서 생성 및 관리되므로 속도가 빠릅니다.
- 커널의 개입을 받지 않기 때문에 이식성(portability)이 높습니다. (모든 운영체제에서 실행할 수 있음)
단점
- 커널에서 스레드가 하나라고 판단하기 때문에 하나의 스레드가 중단되면 나머지 모든 스레드 역시 중단됩니다.
커널 수준 스레드 (Kernel-Level Thread)
커널 수준 스레드는 운영체제가 지원하는 스레드 기능으로 구현되며, 커널이 스레드의 생성 및 스케줄링 등을 관리합니다.
사용자수준 스레드와 커널 수준 스레드가 일대일(1:1)
로 매핑됩니다. 따라서 사용자 수준 쓰레드를 생성하면 이에 대응하는 커널 스레드를 자동으로 생성합니다.
장점
- 커널이 각 스레드를 개별적으로 관리하기 때문에 프로세스 내 스레드들이 병행으로 수행이 가능합니다.
- 그렇기 때문에 하나의 스레드가 중단되도 다른 스레드는 계속 수행이 가능합니다.
단점
- 사용자 스레드보다 생성및 관리 속도가 느립니다.
혼합형 스레드
사용자 수준 스레드와 커널 수준 스레드를 혼합한 구조입니다. 이는 사용자 수준 스레드와 커널수준 스레드의 단점을 극복한 방법입니다.
사용자 수준 쓰레드는 커널 수준 쓰레드와 비슷한 경량 프로세스에 다대다로 매핑되고, 경량 프로세스는 커널 수준 쓰레드와 일대일로 매핑됩니다. 결국 다수의 사용자 수준 쓰레드에 다수의 커널 쓰레드가 다대다(n:m)
로 매핑됩니다.
장점
- 프로세스 내 스레드들이 병행으로 수행이 가능합니다.
- 스레드 풀링 기법을 통해 일대일 스레드 매핑에서의 오버헤드를 줄여줍니다.
스레드 풀링 (Thread pooling)
시스템이 관리하는 쓰레드의 풀을 응용 프로그램에 제공하여 스레드를 효율적으로 사용할 수 있게 하는 방법입니다. 즉, 미리 생성한 스레드를 재사용하도록 하여 스레드를 생성하는 시간을 줄여 시스템의 부담을 덜어줍니다. 또한 동시에 생성할 수 있는 스레드수를 제한하여 시스템의 자원 소비를 줄여서 응용 프로그램의 전체 성능을 일정 수준으로 유지합니다.