import ( "코딩", "행복", "즐거움" )

고루틴?? 본문

GO

고루틴??

더코드마니아 2023. 2. 23. 14:10

 

 

 

Go 언어에서 고루틴(Goroutine)은 경량 스레드(lightweight thread)로, 병행성(Concurrency)을 구현하는 핵심 요소입니다. 고루틴은 매우 가볍고, 스레드와 달리 스택과 컨텍스트 스위칭 비용이 적어서 많은 수의 고루틴을 생성하고 실행하는 것이 가능합니다.

 

고루틴은 다음과 같은 구조로 이루어져 있습니다.

 

고루틴 스택(Stack)


고루틴은 스택을 가지며, 함수의 호출과 반환 등을 처리하는 데 사용됩니다. Go 언어는 고루틴이 시작될 때, 자동으로 스택을 할당하고 크기를 조절합니다.

각 고루틴이 사용하는 스택(Stack)으로,  스택은 LIFO(Last In First Out) 구조로 되어 있어서, 가장 나중에 쌓인 데이터가 가장 먼저 꺼내지게 됩니다.

 

고루틴 스택도 마찬가지로 가장 나중에 실행된 함수가 가장 먼저 반환되어 스택에서 꺼내지게 됩니다. 자료구조에 대해서 아시는 분은 매우 간단한 원리이죠.

 

고루틴 스택은 고루틴이 실행되면 자동으로 생성되는데, 각 고루틴은 자신만의 스택을 가지고 있으며, 스택은 고루틴이 사용하는 메모리 공간 중 하나입니다. 스택은 고루틴이 함수를 호출할 때마다 새로운 프레임(Frame)을 스택에 추가하고, 함수가 반환될 때마다 프레임을 스택에서 제거합니다. 이렇게 스택에 쌓이고 제거되는 프레임은 각 함수의 지역 변수, 매개 변수, 반환 주소 등의 정보를 저장합니다.

 

Go 언어에서는 각 고루틴의 스택 크기를 2KB로 제한합니다. 따라서 고루틴에서 사용하는 메모리가 매우 많아지는 경우, 스택 오버플로(Stack Overflow)가 발생할 수 있습니다. 이러한 경우에는 스택 크기를 더 크게 설정하거나, 동적으로 메모리를 할당하여 해결할 수 있습니다.

 

또한, 고루틴에서는 스택에 대한 별도의 관리가 필요합니다. 스택이 너무 커지면 메모리를 많이 사용하게 되고, 스택이 너무 작으면 스택 오버플로가 발생할 가능성이 높아집니다. 따라서 Go 런타임은 고루틴 스택의 크기를 동적으로 조정하여 메모리 사용량을 최적화하고, 스택 오버플로를 방지합니다. 이를 통해 Go 언어는 수많은 고루틴을 효율적으로 관리할 수 있습니다.

 


PC(Program Counter)

고루틴은 현재 실행 중인 코드의 위치를 추적하기 위해 PC(Program Counter) 값을 유지합니다.

프로그램 카운터(Program Counter)의 개념에 대한 이해가 필요한데요..  컴퓨터 아키텍처에서 중요한 개념 중 하나로 현재 실행 중인 명령문의 주소를 저장하는 레지스터(register)입니다.

CPU는 프로그램 카운터에 저장된 주소로부터 명령어를 가져와 실행합니다.

프로그램 카운터는 컴퓨터가 명령어를 순서대로 실행하는 데 매우 중요한 역할을 합니다. 
프로그램이 실행될 때, CPU는 첫 번째 명령어의 주소를 프로그램 카운터에 저장하고, 해당 주소로부터 명령어를 가져와 실행합니다. 이후에는 다음 명령어의 주소를 계산하여 프로그램 카운터에 저장하고, 해당 주소로부터 명령어를 가져와 실행합니다. 이를 반복하면서 프로그램이 실행됩니다.

Go 언어에서도 프로그램 카운터가 중요한 역할을 합니다. 예를 들어, 고루틴(Goroutine)은 현재 실행 중인 코드의 위치를 추적하기 위해 프로그램 카운터 값을 유지합니다. 또한, defer 함수가 실행될 때도 프로그램 카운터를 이용하여 함수 반환 직전에 실행될 코드의 위치를 지정합니다.

프로그램 카운터는 컴퓨터 아키텍처에서 매우 중요한 개념 중 하나이며, Go 언어에서도 매우 중요한 역할을 합니다.

 

 


G(Ptr)

 

고루틴 구조체는 G(Ptr) 포인터를 가지며, 해당 고루틴의 상태와 메모리 할당 정보 등을 저장합니다.

G는 Go 언어에서 고루틴(Goroutine)을 나타내는 구조체(Struct)입니다. G 구조체는 각 고루틴의 상태를 저장하고, 고루틴 스택과 프로그램 카운터(Program Counter) 등의 정보를 가지고 있습니다.

G 구조체는 포인터(Pointer) 형태로 사용되며, 일반적으로 *G 또는 G* 형태로 사용됩니다. 포인터 형태로 사용하는 이유는 고루틴을 생성할 때마다 새로운 G 구조체가 생성되기 때문입니다. 따라서 각 고루틴은 자신만의 G 구조체를 가지고 있으며, 이를 포인터 형태로 전달함으로써 고루틴 간의 정보를 공유할 수 있습니다.

G 구조체는 Go 언어의 내부적인 구조체이므로, 일반적으로 프로그래밍에서 직접 사용되는 경우는 적습니다. 그러나 디버깅(Debugging)이나 성능 분석 등의 작업에서 G 구조체를 이용하여 고루틴의 상태나 정보를 확인하는 경우가 있습니다. 또한 Go 언어의 런타임(Runtime) 시스템에서는 G 구조체를 사용하여 고루틴을 관리하고, 스케줄링을 수행합니다.

 

이외에도 Defer 스택, 스케줄링, 채널 등의 핵심 요소들로 구성되어 있으며, 

이와 같은 구조로 고루틴은 매우 가볍고 효율적으로 동작합니다. 고루틴은 Go 언어에서 독특한 기능으로, Go 언어의 가장 강력한 기능 중 하나입니다.

'GO' 카테고리의 다른 글

API 서버에서의 오류 설계  (0) 2023.03.13
Golang sync.Pool 기본 원리  (0) 2023.03.03
Go 리플렉션 성능이슈  (0) 2022.11.16
GO 백엔드 개발자 학습 로드맵  (0) 2022.11.16
GO 디자인 패턴에 관심이 있다면 ??  (0) 2022.11.16