GoRoutine
GoRoutine은 Go언어의 빠른 병렬 처리를 도와주는 경량 스레드이다. 많은 개발자들이 Go를 채택하는 많은 이유 중 하나가 바로 이 GoRoutine이 있기 때문이라고 생각한다. GoRoutine은 OS thread보다 매우 가볍기 때문에 생성 및 관리 비용이 적고, 컨텍스트 스위칭 오버헤드가 적기 때문에 높은 처리량과 낮은 코스트를 보장한다. 또한 구현이 매우 간단해 빠른 개발을 도와준다. 아래는 AI가 작성한 내용이다.
Go 언어의 핵심 기능 중 하나인 GoRoutine은 경량 쓰레드로, 일반적인 멀티 스레딩과 달리 OS 쓰레드보다 훨씬 가볍고 효율적으로 동작합니다. GoRoutine은 Go 런타임에 의해 관리되며, go 키워드를 사용하여 함수를 호출하면 해당 함수가 새로운 GoRoutine에서 실행됩니다. 즉, 메인 GoRoutine과 동시에 실행되어 병렬 처리가 가능해집니다.
GoRoutine은 자체 스택을 가지지만 필요에 따라 스택 크기를 동적으로 조절할 수 있어 메모리 사용량을 줄이고 효율성을 높입니다. 또한, Go 런타임의 Go Scheduler를 통해 GoRoutine들을 관리하고 실행하며, 여러 GoRoutine을 OS 쓰레드에 효율적으로 분배하여 실행합니다.
GoRoutine은 멀티 스레딩에 비해 여러 가지 장점을 지니고 있습니다. 첫째, OS 쓰레드보다 가볍기 때문에 생성 및 관리 비용이 적고 Context Switching 오버헤드도 줄일 수 있습니다. 둘째, Go Scheduler가 GoRoutine을 효율적으로 관리하여 시스템 자원을 최대한 활용합니다. 셋째, go 키워드 하나로 간편하게 병행 처리를 구현할 수 있습니다. 넷째, 채널을 통해 GoRoutine 간 데이터 공유를 안전하게 수행할 수 있습니다.
GoRoutine과 함께 사용되는 Channel은 GoRoutine 간의 통신을 위한 파이프라인입니다. 채널을 통해 GoRoutine들은 데이터를 안전하게 주고받을 수 있으며, 동기화 문제 없이 병행 처리를 할 수 있습니다. 채널은 make 함수를 사용하여 생성하며, 채널 연산자(<-)를 사용하여 데이터를 주고받습니다.
채널은 버퍼 유무에 따라 버퍼링된 채널과 버퍼링되지 않은 채널로 나뉩니다. 버퍼링된 채널은 버퍼에 데이터를 저장할 수 있는 채널이며, 버퍼링되지 않은 채널은 데이터를 즉시 전송해야 하는 채널입니다. 버퍼링되지 않은 채널을 사용하면 GoRoutine들이 동기화되어 실행됩니다.
GoRoutine과 Channel은 Go 언어의 강력한 병행 처리 기능을 제공하며, 복잡한 병렬 프로그램을 효율적이고 안전하게 개발할 수 있도록 지원합니다.
GoRoutine은 아래와 같이 함수를 실행하는 부분에 "Go" 키워드 하나만 붙혀 사용할 수 있다. 출력 결과를 보면 GoRoutine에 의해 호출 함수가 순서대로 실행되지 않았고, 병렬처리 된 것을 볼 수 있다. 아래 코드에서 유의해야할 점은 Go는 실행시 main() 함수를 가장 먼저 찾으며 main() 함수 또한 하나의 GoRoutine 위에서 실행된다. main() 함수가 종료되면 프로그램이 종료되기 때문에 다른 GoRoutine들이 작업을 완료하지 못하더라도 함께 종료된다. 때문에 예제 코드에서 임시로 Sleep을 걸어둔 것이다.
func main() {
for i := 1; i <= 5; i++ {
go printNumber(i)
}
time.Sleep(time.Second * 3)
}
func printNumber(number int) {
for i := 0; i < 3; i++ {
fmt.Println("number =", number)
}
}
Channel
Channel은 GoRoutine간 정의된 데이터타입의 데이터들을 송수신 할 수 있게 도와주는 데이터 파이프라인이다. Channel은 아래와 같이 <- 키워드를 이용해 데이터의 흐름을 제어할 수 있으며, Channel을 이용해 비동기로 동작하는 GoRoutine간 데이터를 안전하게 전달할 수 있다.
// 양방향 채널
ch := make(chan int)
// 단방향 채널 (송신 전용)
sendCh := make(chan<- int)
// 단방향 채널 (수신 전용)
recvCh := make(<-chan int)
func main() {
ch := make(chan int)
for i := 1; i <= 5; i++ {
go sum(i, i+1, ch)
}
for i := 1; i <= 5; i++ {
fmt.Println(<-ch)
}
time.Sleep(time.Second * 3)
}
func sum(a int, b int, ch chan<- int) {
ch <- a + b
}
Reference