[go] race condition을 방지하기 위한 sync 패키지의 기능

Race condition은 여러 고루틴이 동시에 하나의 자원에 접근할 때 발생하는 문제입니다. sync 패키지는 이러한 상황을 방지하기 위한 도구를 제공합니다. 여기에서는 sync.Mutexsync.WaitGroup의 기능에 대해 알아보겠습니다.

sync.Mutex

sync.Mutex는 고루틴이 공유 데이터에 안전하게 접근할 수 있도록 하는 동시성 제어 방법 중 하나입니다. 아래는 sync.Mutex를 사용하여 공유 데이터에 안전하게 접근하는 예제입니다.

package main

import (
    "fmt"
    "sync"
)

var (
    mu      sync.Mutex
    balance int
)

func deposit(amount int) {
    mu.Lock()
    defer mu.Unlock()
    balance += amount
    fmt.Printf("Deposited %d\n", amount)
}

func withdraw(amount int) {
    mu.Lock()
    defer mu.Unlock()
    if balance >= amount {
        balance -= amount
        fmt.Printf("Withdrawn %d\n", amount)
    } else {
        fmt.Println("Insufficient balance")
    }
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(2)

    go func() {
        defer wg.Done()
        deposit(200)
    }()

    go func() {
        defer wg.Done()
        withdraw(100)
    }()

    wg.Wait()

    fmt.Printf("Balance: %d\n", balance)
}

위 예제에서 sync.Mutex를 사용하여 depositwithdraw 함수에서 balance 변수에 안전하게 접근하고 있습니다.

sync.WaitGroup

sync.WaitGroup은 고루틴이 모두 종료될 때까지 기다리는 동안 사용됩니다. 아래는 sync.WaitGroup을 사용하여 고루틴이 모두 종료될 때까지 기다리는 예제입니다.

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }

    wg.Wait()
    fmt.Println("All workers done")
}

위 예제에서는 sync.WaitGroup을 사용하여 모든 고루틴이 종료되기를 기다리고 있습니다.

이처럼 sync 패키지의 sync.Mutexsync.WaitGroup을 사용하여 race condition을 방지할 수 있습니다.

이러한 도구들을 사용하면 고루틴 간의 안전한 데이터 공유 및 동기화를 보장할 수 있습니다.

더 자세한 내용은 공식 Go 문서를 참고할 수 있습니다.