ホームページ  >  記事  >  バックエンド開発  >  生産者と消費者のパターン

生産者と消費者のパターン

王林
王林オリジナル
2024-07-27 14:35:15831ブラウズ

Producer-Consumer Pattern

この投稿では、ゴルーチンとチャネルについて紹介します。これらは Go で最も便利な 2 つの構造です。これらを適切に使用すると、開発者は同時実行性を非常に柔軟に処理できます。それらはインタビューで最も一般的なトピックの 1 つです。

シンプルなプロデューサー コンシューマー パターンを Go に実装します。

var buffer = make(chan int, 5)

func produce(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 10; i++ {
        buffer <- i
        time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))
    }
    fmt.Println("producer done")
}

func consume(wg *sync.WaitGroup) {
    defer wg.Done()
    for data := range buffer {
        fmt.Println(data)
        time.Sleep(time.Millisecond * time.Duration(rand.Intn(400)))
    }
    fmt.Println("consumer done")
}

func main() {
    var producerWg sync.WaitGroup
    var consumerWg sync.WaitGroup
    producerWg.Add(1)
    go produce(&producerWg)
    go func() {
        producerWg.Wait()
        close(buffer)
        fmt.Println("closed channel")
    }()
    consumerWg.Add(1)
    go consume(&consumerWg)
    consumerWg.Wait()
    fmt.Println("done")
}

これは最も単純な実装の 1 つです。しかし、このパターンは非常に一般的です。値を「生成」するスレッドと、値を「消費」する必要があるスレッドがあります。 golang では、スレッド間でこれらの値を渡す方法はチャネルです。

まず、整数用のチャネルを作成します。次に、プロデューサー関数とコンシューマー関数を実装するルーチンを作成します。

マルチスレッドの状況では、同期が問題になります。 Golang は、同期を実装する手段の 1 つとして WaitGroup を作成しました。これらは単にカウンターとして機能し、同期する必要があるスレッドはカウントが 0 になるまで待機します。制御スレッドは Done() 関数を使用してカウンターをデクリメントします。

この問題では、プロデューサーとコンシューマーの両方に WaitGroup を作成し、両方をカウント 1 に初期化します (Add() 関数を使用)。

メイン スレッドはプロデューサー、コンシューマー、およびプロデューサーを待機するインライン スレッドを起動し、その後コンシューマーが完了するのを待ちます。

プロデューサー スレッドは通常どおりデータの送信を開始します。完了すると、WaitGroup を使用して、チャネルへの送信が完了したことを通知します。インライン goroutine は、チャネルを閉じるプロデューサー WaitGroup を待機します。チャネルが閉じられない場合、コンシューマはさらなるデータを待って永遠にスリープ状態になり、プロセスは決して終了しません。

コンシューマにデータがなくなると (チャネルが閉じられたため)、2 番目の WaitGroup に完了を通知します。

プロデューサー スレッドとコンシューマー スレッドを起動したメイン スレッドは、コンシューマー WaitGroup が完了を許可するまで待機します。これにより、メインスレッドが途中で終了し、プロセス内のすべてのスレッドが強制終了されるのを防ぎます。

これは、生産者と消費者のパターンを実装する唯一の方法ではありません。

SIGTERM や SIGINT などのシグナルからの外部終了など、製品コードで対処する必要がある問題もいくつかあります。これは基本を示す簡単なデモンストレーションです。

他にどのように実装しますか?上記の実装には何が欠けていますか?コメントや他の実装へのリンクを以下に投稿してください。

ありがとうございます!

この投稿とこのシリーズのすべての投稿のコードはここにあります

以上が生産者と消費者のパターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。