Heim  >  Artikel  >  Backend-Entwicklung  >  Produzenten-Konsumenten-Muster

Produzenten-Konsumenten-Muster

王林
王林Original
2024-07-27 14:35:15745Durchsuche

Producer-Consumer Pattern

In diesem Beitrag werden Goroutinen und Kanäle vorgestellt. Dies sind zwei der nützlichsten Konstrukte in Go. Zusammen bieten sie Entwicklern bei richtiger Verwendung große Flexibilität im Umgang mit Parallelität. Sie gehören zu den häufigsten Themen in einem Vorstellungsgespräch.

Implementieren Sie ein einfaches Producer-Consumer-Muster in 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")
}

Dies ist eine der einfachsten Implementierungen; aber das Muster ist recht häufig. Wir haben einen Thread, der Werte „produziert“, und einen Thread, der sie „verbrauchen“ muss. In Golang ist die Art und Weise, diese Werte zwischen Threads zu übergeben, ein Kanal.

Wir beginnen mit der Erstellung eines Kanals für die Ganzzahlen. Erstellen Sie dann die Routinen, die die Producer- und Consumer-Funktionen implementieren.

In jeder Multithread-Situation ist die Synchronisierung ein Problem. Golang hat WaitGroups als eine Möglichkeit zur Implementierung der Synchronisierung erstellt. Sie funktionieren einfach als Zähler und ein Thread, der synchronisiert werden muss, wartet, bis der Zählerstand 0 ist. Ein steuernder Thread verwendet die Funktion Done(), um den Zähler zu dekrementieren.

In diesem Problem erstellen wir eine WaitGroup sowohl für den Produzenten als auch für den Konsumenten und initialisieren beide, um 1 zu zählen (mithilfe der Add()-Funktion).

Der Hauptthread startet den Produzenten, den Konsumenten und einen Inline-Thread, der auf den Produzenten wartet und dann auf den Abschluss des Konsumenten wartet.

Der Producer-Thread beginnt normal mit dem Senden von Daten. Wenn es fertig ist, verwendet es die WaitGroup, um zu signalisieren, dass das Senden an den Kanal abgeschlossen ist. Die Inline-Goroutine wartet auf die Produzent-WaitGroup, die den Kanal schließt. Wenn der Kanal niemals geschlossen wird, würde der Verbraucher ewig schlafen und auf weitere Daten warten, und der Prozess würde niemals beendet werden.

Wenn der Verbraucher keine Daten mehr hat (weil der Kanal geschlossen wurde), benachrichtigt er die zweite WaitGroup, dass der Vorgang abgeschlossen ist.

Der Hauptthread, der die Producer- und Consumer-Threads gestartet hat, wartet, bis die Consumer-WaitGroup den Abschluss zulässt. Dadurch wird verhindert, dass der Hauptthread vorzeitig beendet wird, was alle Threads im Prozess töten würde.

Dies ist nicht die einzige Möglichkeit, das Produzenten-Konsumenten-Muster umzusetzen.

Es gibt auch einige Probleme wie die externe Beendigung durch Signale wie SIGTERM und SIGINT, die für Produktionscode behoben werden müssten. Dies ist eine einfache Demonstration, die die Grundlagen zeigt.

Wie würden Sie es sonst umsetzen? Was fehlt in der obigen Implementierung? Veröffentlichen Sie unten Ihre Kommentare oder Links zu anderen Implementierungen.

Danke!

Den Code für diesen Beitrag und alle Beiträge dieser Reihe finden Sie hier

Das obige ist der detaillierte Inhalt vonProduzenten-Konsumenten-Muster. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn