Go 언어는 병행성(Concureency, 동시성)을 제공함
병행성과 병렬성(Paraleelism)은 서로 다른 개념
병행성
병렬성
동시성(병행성)은 두 개 이상의 작업이 동시에 진행되도록 프로그램을 구성하는 것과 관련됨
병렬성은 두 개 이상의 작업이 동시에 실행되도록 함
병렬 처리에는 둘 이상의 프로세서나 스레드가 필요하지만 동시성은 필요 없음
다음은 동시성의 예제
2개의 Task를 Processor에서는 번갈아 가면서 진행함
두 Task 사이에 전환 시간은 매우 짧음으로 인간이 느끼기에 동시에 실행된다고 느껴짐
다음은 병행성에 예제
여러개의 프로세스를 통해 여러개의 문제를 동시에 실행함(물리적, 시간적으로 동시)
병렬성을 사용해 복잡한 한개의 문제를 작은 조각으로 나눠 동시에 실행해 전체 문제가 해결되는 속도를 높일 수 있음
만약 단 1개의 프로세서만 존재한다면, 순차적으로 처리됨
Go의 동시성
Go에서 동시성을 활용하기 위해 고루틴을 사용함
고루틴은 자체 스레드 또는 프로세스에서 실행되지 않음
Go 런타임은 고루틴을 계속 실행하기 위해 필요에 따라 스레드에 고루틴을 동적으로 다중화 함
다음은 동시성을 테스트하기 위한 예제
package main
import (
"fmt"
"time"
)
func numSearch(targetVal int) {
searchList := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
time.Sleep((time.Duration(targetVal) * 100) * time.Millisecond)
for _, num := range searchList {
if num == targetVal {
fmt.Printf("I found the targetVal: %d \n", targetVal)
return
}
}
fmt.Println("targetVal not found :(")
}
func main() {
numSearch(10)
numSearch(1)
// time.Sleep(10000 * time.Millisecond)
fmt.Println("The program has finished executing.")
}
// 실행 결과
I found the targetVal: 10
I found the targetVal: 1
The program has finished executing.
마지막 두번쨰 줄 time.Sleep
을 주석 상태로 실행하면 코드가 순차적으로 실행됨을 확인 가능
numSearch
함수를 확인하면 time.Duration
에 넘겨지는 targetVal이 높을 수록 나중에 실행됨을 알 수 있음
즉, 매개변수를 1을 전달할 때보다 10을 전달할 때 실행하는 데 더 오래걸림
하지만 함수 호출이 순차적으로 실행 되기 때문에 두 번째 호출은 첫 번째 호출이 완료될 떄까지 시작되지 않음
만약 numSearch
함수를 고루틴으로 바꾸면 다른 결과가 나옴
package main
import (
"fmt"
"time"
)
func numSearch(targetVal int) {
searchList := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
time.Sleep((time.Duration(targetVal) * 100) * time.Millisecond)
for _, num := range searchList {
if num == targetVal {
fmt.Printf("I found the targetVal: %d \n", targetVal)
return
}
}
fmt.Println("targetVal not found :(")
}
func main() {
go numSearch(10) // 고루틴으로 변경
go numSearch(1) // 고루틴으로 변경
time.Sleep(10000 * time.Millisecond) // 주석 해제
fmt.Println("The program has finished executing.")
}
// 실행 결과
I found the targetVal: 1
I found the targetVal: 10
The program has finished executing.
결과를 보면 두번째로 호출된 numSearch(1)
의 결과가 먼저 출력되었는데 고루틴을 통해 첫 번째 호출인 numSearch(10)
의 결과를 기다리지 않았기 때문
위는 간단한 예제로 동시성의 이점을 살릴 수 있는 상황중 하나를 예시로 설명하고자 함
사용자 요청을 처리하기 위한 서버가 여러개로 분산화 되어있는 상황
순차적으로 처리하는 경우, 1번 서버, 2번 서버에 요청을 보내고 대기하면서 해당 서버가 요청이 처리 가능한 판별
순차적 방식은 효율적인 선택을 보장하지 못함
처리 가능한 느린 2번 서버와 빠른 5번 서버가 존재하는 경우, 먼저 응답을 받은 2번 서버를 선택
동기적으로 처리하는 경우 만약 10개의 서버가 존재한다면, 10개 서버에 동시에 요청을 보내고 대기,
이후 응답이 돌아온 서버 중 사용자 요청을 처리 가능하면서 가장 빨리 응답이 되돌아온 서버를 선택하고, 기존 미해결 프로세스(다른 서버에 요청을 보내고 대기하는 등..)를 종료 가능
동시성은 작업을 수행하기 위해 병렬성을 사용할 수 있지만 병렬성이 동시성의 궁극적인 목표는 아님
동시성은 독립적인 여러 작업을 한 번에 수행하도록 설계하는 쪽에 무게를 둔 개념
병렬성은 하나의 작업을 설계된 대로 분할해서 동시에 수행하는 쪽에 무게를 둔 개념
Concurrency is about dealing with lots of things at once.
Parallelism is about doing lots of things at once동시성은 여러 가지 일을 한 번에 처리 하는 것
병렬성은 여러 가지 일을 한 번에 수행 하는 것
- Go Concurrency Patterns, Rob Pike -