ホームページ  >  記事  >  バックエンド開発  >  golang の Barrier について話しましょう

golang の Barrier について話しましょう

PHPz
PHPzオリジナル
2023-04-11 09:10:37882ブラウズ

並行コードを記述する場合、多くの場合、データの競合や競合状態を防ぐために、複数の goroutine と相互のトークンまたはロックの間の同期を確保する必要があります。 Go 言語には、chan および sync パッケージを通じてこれらの同期を実現するメカニズムがいくつか用意されていますが、柔軟性が十分ではなく、より高度な同期方法が必要になる場合があり、この場合はバリアを使用する必要があります。

バリアは、次の操作に進む前に、ゴルーチンのグループが同時に操作を完了するのを待つために使用される同期プリミティブです。これは非常に一般的な同期メカニズムです。 Golang は、「Barrier」というバリアを実装するメカニズムも提供します。

バリアの原理は、ゴルーチンのグループを 2 つのステージに分割することです。最初のステージでは、各ゴルーチンは自身のタスクを完了した後に停止し、他のゴルーチンが完了するのを待ちます。第 2 ステージでは、すべてのゴルーチンが完了すると、 goroutines has completed 停止して相互にシグナルを設定すると、すべての goroutines が同時に実行を再開します。

Golang は、同期パッケージで "WaitGroup" タイプを提供します。待機中のゴルーチンの数を追加するには、Add メソッドを使用します。各ゴルーチンがタスクを完了した後、WaitGroup へのカウンターを減らすために Done メソッドを使用します。 , Wait メソッドはブロックされます。カウンターがゼロになるまで、つまりすべてのゴルーチンがタスクを完了するまで、次のステップは続行されません。

ただし、WaitGroup には欠点があり、一定数の goroutine が完了するまでしか待機できないため、新しい goroutine が参加すると使用できなくなります。現時点では、バリアを使用してこの問題を解決できます。

Barrier は、任意の数のゴルーチンで使用でき、各ステージの最後に指定された操作を実行できます。これには、一連の操作の完了を待っているゴルーチンの数を示すカウンターと、各ステージの最後に実行する関数が含まれています。

Golang の「待機スレッドのグループ」は、同期パッケージの「WaitGroup (待機グループ)」を使用して実装できます。

var wg sync.WaitGroup

func worker() {
    defer wg.Done()
    // 执行自己的任务
}

func main() {
    for i := 0; i < n; i++ {
        wg.Add(1)
        go worker()
    }
    // 等待所有线程完成
    wg.Wait()
}

次に、「Barrier」を使用してサンプルを作成します。ゴルーチンの変更:

package main

import "fmt"
import "sync"

func main() {
    b := sync.NewCond(&sync.Mutex{})
    done := make(chan bool)

    worker := func(id int) {
        defer func() {
            fmt.Printf("Worker %d done\n", id)
            done <- true
        }()
        fmt.Printf("Worker %d processing\n", id)
        b.L.Lock()
        b.Wait() // 等待阻塞直到b.Broadcast()被执行
        b.L.Unlock()
        fmt.Printf("Worker %d resumed\n", id)
    }

    go func() {
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go worker(i)
        }
    }()

    go func() {
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go worker(i)
        }
    }()

    go func() {
        wg.Wait()
        b.Broadcast()
    }()

    for i := 0; i < 20; i++ {
        <-done
    }
    fmt.Printf("All workers done\n")
}

この例では 20 個のゴルーチンを作成し、2 つのフェーズに分かれています。最初のフェーズは各ゴルーチンがタスクを完了するまで待機し、2 番目のフェーズはすべてのゴルーチンがタスクを完了するまで待機します。完了するまで操作を実行しないでください。

ゴルーチンのグループが 2 つ作成されると、ゴルーチンの 1 つが「待機」を呼び出し、すべてのゴルーチンがタスクを完了するまでブロックします。他のスレッドがタスクを完了すると、ブロックが解除され、「ブロードキャスト」を使用してすべてのゴルーチンにシグナルが送信され、次のステップに進みます。

つまり、Golang の Barrier を使用すると、より高度なレベルで同時操作を同期し、コードの堅牢性と信頼性を高めることができます。

以上がgolang の Barrier について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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