>백엔드 개발 >Golang >Go의 동시성 디코딩: 고루틴 스케줄링

Go의 동시성 디코딩: 고루틴 스케줄링

Barbara Streisand
Barbara Streisand원래의
2025-01-14 22:08:45724검색

Go

나. 고루틴: Go의 동시성 모델에 대한 심층 분석

고루틴은 Go 디자인의 초석으로, 동시 프로그래밍을 위한 강력한 메커니즘을 제공합니다. 경량 코루틴으로서 병렬 작업 실행을 단순화합니다. 고루틴 실행은 간단합니다. 함수 호출 앞에 go 키워드를 붙여 비동기 실행을 시작하기만 하면 됩니다. 고루틴이 완료될 때까지 기다리지 않고 메인 프로그램이 계속됩니다.

<code class="language-go">go func() { // Launch a goroutine using the 'go' keyword
    // ... code to be executed concurrently ...
}()</code>

II. 고루틴의 내부 메커니즘 이해

개념적 기초

동시성 대 병렬성

  • 동시성: 단일 CPU에서 동시에 여러 작업을 관리하는 능력입니다. CPU는 작업 간을 빠르게 전환하여 병렬 실행이라는 착각을 불러일으킵니다. 미시적으로는 순차적이지만 거시적으로는 동시적으로 나타납니다.

  • 병렬성: 여러 CPU에서 여러 작업을 동시에 실행하여 CPU 리소스 경합을 제거합니다.

프로세스와 스레드

  • 프로세스: 자체 리소스(메모리, 파일 등)를 갖춘 독립형 실행 환경입니다. 프로세스 간 전환은 리소스 집약적이며 커널 수준 개입이 필요합니다.

  • 스레드: 프로세스 내의 경량 실행 단위로, 프로세스의 리소스를 공유합니다. 스레드 전환은 프로세스 전환보다 오버헤드가 적습니다.

코루틴

코루틴은 자체 레지스터 컨텍스트와 스택을 유지합니다. 코루틴 간 전환에는 이 상태를 저장하고 복원하여 중단된 부분부터 실행을 재개할 수 있는 작업이 포함됩니다. 프로세스 및 스레드와 달리 코루틴 관리는 운영 체제가 아닌 사용자 프로그램 내에서 처리됩니다. 고루틴은 특정 유형의 코루틴입니다.

GPM 일정 모델

Go의 효율적인 동시성은 GPM 스케줄링 모델에 의존합니다. M, P, G 및 Sched의 네 가지 주요 구성 요소가 관련됩니다(Sched는 다이어그램에 표시되지 않음).

  • M(머신): 커널 수준 스레드입니다. 고루틴은 Ms.

    에서 실행됩니다.
  • G(고루틴): 단일 고루틴입니다. 각 G에는 자체 스택, 명령어 포인터 및 기타 예약 관련 정보(예: 대기 중인 채널)가 있습니다.

  • P(Processor): 고루틴을 관리하고 실행하는 논리 프로세서입니다. 준비된 고루틴의 실행 대기열을 유지합니다.

  • Sched(Scheduler): M 및 G 대기열을 관리하고 효율적인 리소스 할당을 보장하는 중앙 스케줄러입니다.

예약 진행

Go

다이어그램은 고루틴을 실행하는 프로세서(P)가 있는 두 개의 OS 스레드(M)를 보여줍니다.

  • GOMAXPROCS()은 P 개수(따라서 실제 동시성 수준)를 제어합니다.

  • 회색 G가 준비되었지만 아직 실행되지 않았습니다. P는 이 실행 대기열을 관리합니다.

  • 고루틴을 실행하면 P의 실행 대기열에 추가됩니다.

Go

M0이 차단되면 P는 M1으로 전환합니다(스레드 캐시에서 검색할 수 있음).

Go

P가 작업을 빨리 완료하면 효율성을 유지하기 위해 다른 P의 작업을 훔칠 수도 있습니다.

III. 고루틴으로 작업하기

기본 사용법

고루틴 실행을 위한 CPU 수를 설정합니다(최근 Go 버전의 기본 설정이면 일반적으로 충분합니다).

<code class="language-go">go func() { // Launch a goroutine using the 'go' keyword
    // ... code to be executed concurrently ...
}()</code>

실제 사례

예시 1: 간단한 고루틴 계산

<code class="language-go">num := runtime.NumCPU() // Get the number of logical CPUs
runtime.GOMAXPROCS(num) // Set the maximum number of concurrently running goroutines</code>

고루틴 오류 처리

고루틴에서 처리되지 않은 예외는 전체 프로그램을 종료할 수 있습니다. 패닉을 처리하려면 recover() 문 내에서 defer을 사용하세요.

<code class="language-go">package main

import (
    "fmt"
    "runtime"
)

func cal(a, b int) {
    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    for i := 0; i < 10; i++ {
        go cal(i, i+1)
    }
    //Note:  The main function exits before goroutines complete in this example.  See later sections for synchronization.
}</code>

고루틴 동기화

고루틴은 비동기적으로 실행되므로 완료되기 전에 기본 프로그램이 종료될 수 있습니다. 동기화를 위해 sync.WaitGroup 또는 채널을 사용하세요:

예 1: sync.WaitGroup

사용
<code class="language-go">package main

import (
    "fmt"
)

func addele(a []int, i int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Error in addele:", r)
        }
    }()
    a[i] = i // Potential out-of-bounds error if i is too large
    fmt.Println(a)
}

func main() {
    a := make([]int, 4)
    for i := 0; i < 5; i++ {
        go addele(a, i)
    }
    // ... (add synchronization to wait for goroutines to finish) ...
}</code>

예 2: 동기화를 위해 채널 사용

<code class="language-go">package main

import (
    "fmt"
    "sync"
)

func cal(a, b int, wg *sync.WaitGroup) {
    defer wg.Done()
    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go cal(i, i+1, &wg)
    }
    wg.Wait()
}</code>

고루틴간 통신

채널은 고루틴 간의 통신과 데이터 공유를 용이하게 합니다. 전역 변수도 사용할 수 있지만 더 나은 동시성 제어를 위해서는 일반적으로 채널이 선호됩니다.

예: 생산자-소비자 패턴

<code class="language-go">package main

import (
    "fmt"
)

func cal(a, b int, ch chan bool) {
    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
    ch <- true // Signal completion
}

func main() {
    ch := make(chan bool, 10) // Buffered channel to avoid blocking
    for i := 0; i < 10; i++ {
        go cal(i, i+1, ch)
    }
    for i := 0; i < 10; i++ {
        <-ch // Wait for each goroutine to finish
    }
}</code>

Leapcell: Go를 위한 서버리스 플랫폼

Leapcell은 Go 서비스 배포에 권장되는 플랫폼입니다.

Go

주요 기능:

  1. 다국어 지원: JavaScript, Python, Go, Rust
  2. 무료 무제한 프로젝트: 종량제 가격
  3. 비용 효율적: 유휴 요금이 없습니다.
  4. 개발자 친화적: 직관적인 UI, 자동화된 CI/CD, 실시간 측정항목.
  5. 확장성 및 고성능: 자동 확장, 운영 오버헤드 없음

Go

문서에서 자세히 알아보세요!

Leapcell 트위터: https://www.php.cn/link/7884effb9452a6d7a7a79499ef854afd

위 내용은 Go의 동시성 디코딩: 고루틴 스케줄링의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.