본문 바로가기
프로그래밍/Go언어

Go 언어의 goroutine에 대해서...

by Hwan2 2020. 11. 4.
반응형

기본적으로 C++은 Thread or task or async를 이용해 쓰레드를 만듭니다.

JAVA는 extands Thread을 이용한 run overriding or implements Runnable 을 이용한 run overriding

또는 future클래스를 이용한 Thread 할당 등.... 여러가지 방식으로 Thread를 만들 수 있습니다.


반면 Go언어에서 쓰레드를 사용하려면 go 키워드를 이용한 goroutine을 사용해야 합니다.


1. goroutine vs Thread??

Thread의 경우 기본적으로 stack을 할당받으며, heap, data 영역은 공유를 하게 됩니다.
때문에 프로세스보다 가볍다는 장점과 context 발생시 프로세스보다 빠르다는 점이 있습니다.

Thread는 기본(cpu 코어 * 2) 로 만들어서 돌리는 것이 가장 좋다고 합니다.

하지만 프로그램을 만들다 보면 이렇게 안되죠. 


왜냐?? I/O도 있고, 이벤트 처리, 병렬 처리 등 여러게 사용될 만한 곳이 많이 있습니다.

또한 Thread는 기본적으로 1000개 이상 만들기가 불가능 합니다. 운영체제에서 제안하고 있죠.


그리고 프로세스드보다 가볍지만 쓰레드 또한 context를 유발하기 때문에 성능 저하를 무시 못합니다.

또 Thread를 사용하면 동기화를 해줘야하며, dead lock, race condition 등을 관리해줘야 합니다.




반면, goroutine은 이러한 단점들을 최대한 없앴습니다.


goroutine은 런타임에 돌아가는 멀티플렉싱 방식으로 쓰레드가 동작하게 됩니다.


즉, C++의 논블로킹 방식인 select, epool, IOCP를 생각하시면 될 것 같습니다.

단, 운영체제의 도움을 필요로 하지 않습니다.


즉, goroutine은 round robin방식처럼 조금씩 여러개를 실행하는 동시성을 가지게 됩니다.

때문에 기본적으로 Go언어는 cpu 코어를 1개 사용을 디폴트로 정의하고 있습니다.


만약 여러게의 코어를 설정하고 싶다면 다음과 같이 하면 됩니다.

runtime.GOMAXPROCS(4) // 4개의 CPU 사용


또한 context비용도 Thread에 비해 적게 듭니다.
Thread같은 경우 16개의 범용 레지스터, PC(Program Counter), SP(Stack Pointer), segment 레지스터, 16개의 XMM 레지스터, FP coprocessor state, 16개의 AVX 레지스터, 모든 MSR들 등을 save/restore해야 합니다.

반면 goroutine은 Program Counter, Stack Pointer, DX 이 3개만 사용하며 save/restore 하기 때문에 비용적인 측면에서도 유리합니다.

goroutine은 논블로킹 방식으로 진행합니다.
round robin 방식이기 때문에 sleep이나 네트워크 입력, 채널 오퍼레이션 등이 일어나게 되며 블로킹이 된다면
쓰레드는 이를 무시하고 다른 작업을 하러 갑니다. 

Thread는 할당되면 기본적으로 1MB의 스텍 메모리영역을 할당받게되며, 만들어 지는 비용도 비쌉니다.

때문에 Thread pool이라는 저장공간을 만들고 일정량 이상의 Thread들을 미리 만들어 놓죠.


하지만 goroutine은 KB단위의 스택을 할당 받으며, 링크드 리스트로 관리한다고 합니다. 

즉, 스택이 부족할 경우 동적으로 늘릴 수 있다는 말입니다.


데이터 공유하는 방식도 다릅니다. goroutine은 동기화에 대한 신경을 안써도 됩니다.

Thread는 기본적으로 heap과 data영역을 공유하게 되지만 goroutine은 공유하는 메모리가 없습니다.

goroutine은 채널이라는 파이프라인을 통해 서로 데이터를 주고 받으면서 동기화를 하게 됩니다.

즉, 받는자와 보내는자를 구분해 받는자는 보내는자가 데이터를 보낼때 까지 기다리게 됩니다.

하지만 여기서 blocking이 발생했다고 해서 쓰레드는 이를 계속 기다리지 않고 논 블로킹 방식으로 다른 작업을 하러 갑니다.

round robin방식으로 여러개를 순차적으로 실행할 뿐이죠. 



2. goroutine은 완벽한가?

그건 아닙니다. 동시성에 대한 한계점과 문제점도 존재하며, 
Go언어의 개발자 롭 파이크도 이것에 대한 문제점을 지적하면서
필요에 따라 sync 패키지를 사용하여 유동적으로 코딩하라고 합니다.
sync페키지는 뮤텍스나 조건/상태변수를 이용하여 동시성을 지원해주는 패키지입니다.


3. 마치며...

goroutine에 대해 조사하면서 알게된 사실은 java나 c++ 보다 시스템 자원을 좀 더 알차게 사용할 수 있다는 점입니다.

또한 생산성도 높고 지원하는 라이브러리로 할 수 있는 것들이 생각보다 많다는 것입니다.

알면 알수록 매력적인 언어인 것 같네요!!.


혹시 잘못된 정보나 수정이 필요할 부분이 있다면 댓글로 피드백 남겨주세요!!! 참고해서 수정하도록 하겠습니다.!!


반응형

댓글


스킨편집 -> html 편집에서