> 백엔드 개발 > Golang > Go 동시성: 예제가 포함된 뮤텍스와 채널

Go 동시성: 예제가 포함된 뮤텍스와 채널

Mary-Kate Olsen
풀어 주다: 2025-01-08 20:10:54
원래의
537명이 탐색했습니다.

Go 동시 프로그래밍의 카운터 동기화: 뮤텍스, 버퍼링된 채널 및 버퍼링되지 않은 채널

Go에서 동시 애플리케이션을 구축할 때 공유 데이터에 대한 안전한 액세스를 보장하려면 동기화가 중요합니다. MutexChannel은 Go에서 동기화를 위한 주요 도구입니다.

이 기사에서는 안전한 동시성 카운터를 구축하는 여러 가지 방법을 살펴봅니다. 참조 기사에서는 Mutex을 사용하여 이 문제를 해결하지만 버퍼링된 채널과 버퍼링되지 않은 채널을 사용하는 대안도 살펴보겠습니다.

문제 설명

동시에 안전하게 사용할 수 있는 카운터를 구축해야 합니다.

카운터 코드

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

type Counter struct {
    count int
}

func (c *Counter) Inc() {
    c.count++
}

func (c *Counter) Value() int {
    return c.count
}</code>
로그인 후 복사

코드 동시성을 안전하게 만들기 위해 몇 가지 테스트를 작성해 보겠습니다.

1. 뮤텍스를 사용하세요

Mutex(뮤텍스)는 한 번에 하나의 고루틴만 코드의 중요한 부분에 액세스할 수 있도록 보장하는 동기화 프리미티브입니다. 이는 잠금 메커니즘을 제공합니다. 고루틴이 Mutex을 잠그면 이를 잠그려는 다른 고루틴은 Mutex이 잠금 해제될 때까지 차단됩니다. 따라서 공유 변수나 리소스를 경쟁 조건으로부터 보호해야 할 때 자주 사용됩니다.

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

import (
    "sync"
    "testing"
)

func TestCounter(t *testing.T) {
    t.Run("using mutexes and wait groups", func(t *testing.T) {
        counter := Counter{}
        wantedCount := 1000

        var wg sync.WaitGroup
        var mut sync.Mutex

        wg.Add(wantedCount)

        for i := 0; i < wantedCount; i++ {
            go func() {
                defer wg.Done()
                mut.Lock()
                counter.Inc()
                mut.Unlock()
            }()
        }

        wg.Wait()
        if counter.Value() != wantedCount {
            t.Errorf("got %d, want %d", counter.Value(), wantedCount)
        }
    })
}</code>
로그인 후 복사

이 코드는 sync.WaitGroup을 사용하여 모든 고루틴의 완료를 추적하고, sync.Mutex을 사용하여 여러 고루틴이 동시에 공유 카운터에 액세스하는 것을 방지합니다.

2. 버퍼 채널 사용

Go Concurrency: Mutexes vs Channels with Examples

채널은 Go가 고루틴이 안전하게 통신할 수 있도록 하는 방법입니다. 고루틴 간에 데이터를 전송하고 전달된 데이터에 대한 액세스를 제어하여 동기화를 제공할 수 있습니다.

이 예에서는 채널을 사용하여 고루틴을 차단하고 하나의 고루틴만 공유 데이터에 액세스하도록 허용합니다. 버퍼링된 채널은 용량이 고정되어 있습니다. 즉, 보낸 사람을 차단하기 전에 미리 정의된 수의 요소를 보유할 수 있습니다. 발신자는 버퍼가 가득 찬 경우에만 차단합니다.

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

import (
    "sync"
    "testing"
)

func TestCounter(t *testing.T) {
    t.Run("using buffered channels and wait groups", func(t *testing.T) {
        counter := Counter{}
        wantedCount := 1000

        var wg sync.WaitGroup
        wg.Add(wantedCount)

        ch := make(chan struct{}, 1)

        ch <- struct{}{} // 允许第一个 goroutine 开始

        for i := 0; i < wantedCount; i++ {
            go func() {
                defer wg.Done()
                <-ch
                counter.Inc()
                ch <- struct{}{}
            }()
        }

        wg.Wait()
        if counter.Value() != wantedCount {
            t.Errorf("got %d, want %d", counter.Value(), wantedCount)
        }
    })
}</code>
로그인 후 복사

이 코드는 용량이 1인 버퍼링된 채널을 사용하므로 한 번에 하나의 고루틴만 카운터에 액세스할 수 있습니다.

3. 버퍼링되지 않은 채널을 사용하세요

Go Concurrency: Mutexes vs Channels with Examples

버퍼되지 않은 채널에는 버퍼가 없습니다. 수신자가 데이터를 수신할 준비가 될 때까지 발신자를 차단합니다. 이는 한 번에 하나씩 고루틴 간에 데이터가 전달되는 엄격한 동기화를 제공합니다.

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

import (
    "sync"
    "testing"
)

func TestCounter(t *testing.T) {
    t.Run("using unbuffered channels and wait groups", func(t *testing.T) {
        counter := Counter{}
        wantedCount := 1000

        var wg sync.WaitGroup
        wg.Add(wantedCount)

        ch := make(chan struct{})

        go func() {
            for i := 0; i < wantedCount; i++ {
                ch <- struct{}{}
            }
            close(ch)
        }()

        for range ch {
            counter.Inc()
            wg.Done()
        }

        if counter.Value() != wantedCount {
            t.Errorf("got %d, want %d", counter.Value(), wantedCount)
        }
    })
}
</code>
로그인 후 복사

이 코드는 버퍼링되지 않은 채널을 사용하여 한 번에 하나의 고루틴만 카운터에 액세스하도록 합니다.

4. WaitGroup 대신 버퍼 채널을 사용하세요

WaitGroup 없이 버퍼링된 채널을 사용할 수도 있습니다. 예를 들어 무한 루프나 다른 채널을 사용하여 고루틴 완료를 추적할 수 있습니다.

결론

이 기사에서는 Go에서 안전한 동시성 카운터를 구축하는 다양한 접근 방식을 살펴봅니다. 효율적이고 안전한 동시 Go 프로그램을 작성하려면 이러한 도구와 사용 시기를 아는 것이 중요합니다.

참고자료

이 기사는 "테스트로 Go 배우기"의 동기화 장에서 영감을 받았습니다.

이 기사가 도움이 되기를 바랍니다!

위 내용은 Go 동시성: 예제가 포함된 뮤텍스와 채널의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿