ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Go에서 채널(Channel)을 이용한 고루틴(Goroutine) 개수 제한
    Go 2025. 4. 3. 00:32

    Go의 goroutine은 가벼운 스레드로, 다른 언어보다 손쉽게 동시성을 확보할 수 있게 한다. 하지만 무제한으로 생성하면 메모리 부족이나 시스템 리소스 과부하가 발생할 수 있기 때문에 goroutine의 개수를 제한하는 방법이 필요하다. 이번 글에서는 channel을 이용해 goroutine 개수를 제한하는 방법을 공유한다.


    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func main() {
        maxGoroutines := 10 // 동시에 실행할 최대 goroutine 개수
        semaphore := make(chan struct{}, maxGoroutines)
        
        var wg sync.WaitGroup
        for i := 0; i < 20; i++ {
            wg.Add(1)
            go func(id int) {
                defer wg.Done()
                
                semaphore <- struct{}{} // 세마포어 역할 (슬롯 점유)
                defer func() { <-semaphore }() // 작업 종료 후 슬롯 반환
                
                // 실제 작업 수행
                fmt.Printf("Goroutine %d 실행 중\n", id)
                time.Sleep(1 * time.Second) // 작업 시뮬레이션
            }(i)
        }
        wg.Wait()
        fmt.Println("모든 작업 완료")
    }

     

    코드 설명

    1. 버퍼드 채널을 세마포어로 사용

    semaphore := make(chan struct{}, maxGoroutines)
    • maxGoroutines 개수만큼 버퍼를 가진 채널을 생성한다.
    • 동시에 실행될 수 있는 goroutine의 개수를 제한하는 역할을 한다.

    2. goroutine 시작 전 채널에 값 추가

    semaphore <- struct{}{}
    • 채널에 값을 넣으면서 실행 가능한 goroutine 개수를 제한한다.
    • maxGoroutines 개수만큼만 값이 들어갈 수 있으며, 초과할 경우 블로킹된다.

    3. goroutine 종료 후 채널에서 값 제거

    defer func() { <-semaphore }()
    • 작업이 끝나면 채널에서 값을 제거하여, 새로운 goroutine이 실행될 수 있도록 허용한다.
    • defer를 사용해 goroutine이 종료될 때 자동으로 실행되도록 한다.

    4. WaitGroup을 사용하여 모든 goroutine의 종료 대기

    var wg sync.WaitGroup
    wg.Add(1)  // goroutine 실행 전 카운트 증가
    defer wg.Done() // goroutine 종료 시 카운트 감소
    wg.Wait() // 모든 goroutine 종료까지 대기
    • WaitGroup을 사용하여 모든 goroutine이 종료될 때까지 기다린다.

     

    실행 결과

    Goroutine 0 실행 중
    Goroutine 1 실행 중
    Goroutine 2 실행 중
    ...
    Goroutine 9 실행 중
    (1초 후)
    Goroutine 10 실행 중
    Goroutine 11 실행 중
    ...
    Goroutine 19 실행 중
    모든 작업 완료
    • 최대 10개의 goroutine이 동시에 실행된다
    • 앞의 작업이 끝나야 다음 goroutine이 실행된다.

    요약

    • 채널을 세마포어처럼 활용하여 goroutine 개수를 제한할 수 있다.
    • defer를 이용해 깔끔하게 자원을 반환할 수 있다.
    • sync.WaitGroup을 함께 사용하면 모든 작업이 끝날 때까지 대기할 수 있다.
Designed by Tistory.