멀티 스레드 모델로는 커널 스레드, 사용자 스레드, 멀티 레벨 스레드가 있다. 커널 스레드는 커널이 직접 생성하고 관리하는 스레드이다. 사용자 스레드는 라이브러리로 구현된 일반 스레드이다. 사용자 스레드와 커널 스레드를 사용하기 위해서는 시스템 호출로 커널 기능을 사용해야 한다. 이때의 대응 방식에 따라 모델이 분류된다.
1. 1 to N 모델, 사용자 레벨 스레드 모델
여러 스레드가 커널 스레드 하나와 연결된 방식이다. 운영체제가 멀티스레드를 지원하지 않을 때 사용한 방법이다. 이 방법에서 스레드는 사용자 레벨에서 라이브러리를 사용해 구현되고 라이브러리는 커널 기능을 대신한다. 커널은 사용자 레벨 스레드를 프로세스 하나로 본다.
사용자 레벨 스레드는 여러 스레드를 작동하지만 한 커널 스레드와만 연결된다. 라이브러리가 커널 기능을 대신하기 때문에 문맥 교환이 필요하지 않아 속도가 빠르다. 하지만 여러 스레드가 한 커널 스레드와 연결되기 때문에 커널 스레드가 대기 상태에 들어가면 모든 사용자 스레드가 대기해야 한다. 또한 한 프로세스의 타임 슬라이스(쿼텀)를 여러 스레드가 공유하는 방식이라 멀티코어를 사용할 수 없다. 그리고 커널 레벨에서처럼 공유 변수를 보호하지 않아 보안에 취약하다.
2. 1 to 1 모델, 커널 레벨 스레드 모델
커널 레벨 스레드는 커널이 멀티스레드를 지원하는 방식이다. 한 사용자 스레드에 한 커널 스레드가 연결된다. 한 커널 스레드가 대기 상태가 되어도 다른 커널 스레드에 부착된 스레드는 작업을 계속한다. 그리고 커널 레벨이 공유 변수를 보호해 보안에 취약하지 않으며 커널 기능을 모두 사용한다. 그리고 멀티 코어를 사용하여 효율적이지만 문맥 교환을 할 때 오버헤드가 발생해 느리다.
3. M to N 모델, 멀티 레벨 스레드 모델
하이브리드 스레드라고도 불리며 커널 스레드 개수가 사용자 스레드보다 같거나 적다. 한 커널 스레드가 대기 상태가 되면 다른 커널 스레드가 작업을 대신해 사용자 레벨 스레드보다 효율적으로 작업을 처리한다. 하지만 커널 레벨 스레드에서 발생하는 문맥 교환에 따른 오버헤드를 가져 속도가 저하된다. 그래서 속도가 중요할 때는 사용자 레벨 스레드로 작동하고 보안과 커널 기능이 중요할 때는 커널 레벨 스레드로 작동한다.
Golang만 멀티 스레딩을 지원하는 것이 아니라 JAVA, C++ 등 다양한 프로그래밍 언어에서 멀티 스레딩을 지원합니다. JAVA 스레드와 고루틴을 비교하면
JAVA 스레드 | Golang 고루틴 | |
스택 공간 | 1MB + Guard Page | 2KB |
문맥 교환 비용 | 큼 | 적음 |
생성 및 삭제 비용 | 큼 | 적음 |
고루틴은 멀티 레벨 스레드 모델을 사용합니다. 이 모델은 구현이 어렵지만 Golang은 이를 지원함으로써 효율적인 멀티 스레딩을 가능하게 하였습니다.
참조
고루틴은 어떻게 작동하는가?
stonzeteam.github.io/How-Goroutines-Work/
Goroutines vs Threads
tech.ssut.me/goroutine-vs-threads/
도서
쉽게 배우는 운영체제 chapter03 프로세스와 스레드
'Golang' 카테고리의 다른 글
Go 에서 싱글톤 패턴은 어떻게 작동할까(번역) (0) | 2021.03.21 |
---|---|
Golang, sync.Pool 디자인 이해하기(번역) (0) | 2021.03.21 |
Sort 정렬 인터페이스 구현 (0) | 2021.02.21 |