Heim > Backend-Entwicklung > Golang > Warum führt die Übergabe einer WaitGroup als Wert in Go zu einem Deadlock und wie kann dieser behoben werden?

Warum führt die Übergabe einer WaitGroup als Wert in Go zu einem Deadlock und wie kann dieser behoben werden?

Linda Hamilton
Freigeben: 2024-10-28 18:56:29
Original
618 Leute haben es durchsucht

Why does passing a WaitGroup by value in Go lead to a deadlock, and how can it be resolved?

Deadlock bei Go-Kanälen: Ein Problem unterschiedlicher Tragweite

In einem Golang-Programm erleichtern Kanäle die Kommunikation zwischen Goroutinen. Der Missbrauch von Kanälen kann jedoch zu Deadlocks führen, wie im folgenden Code gezeigt:

<br>package main</p>
<p>import (</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"fmt"
"sync"
Nach dem Login kopieren
Nach dem Login kopieren

)

func push(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
Nach dem Login kopieren
Nach dem Login kopieren

}

func pull(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
Nach dem Login kopieren
Nach dem Login kopieren

}

func main() {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, wg)
go pull(c, wg)

wg.Wait() // Block the main thread until goroutines complete
Nach dem Login kopieren

}

Beim Ausführen dieses Programms kann Folgendes auftreten der folgende Fehler:

fatal error: all goroutines are asleep - deadlock!
Nach dem Login kopieren

Um zu verstehen, warum dieser Deadlock auftritt, schauen wir uns den Code an:

  • main erstellt eine WaitGroup, einen Kanal c und Goroutinen für Push und Pull Operationen.
  • Die Push- und Pull-Funktionen verwenden die WaitGroup, um ihre Ausführung zu synchronisieren.
  • Die Push-Funktion sendet Werte in einer Schleife an c und signalisiert deren Abschluss durch Aufrufen von wg.Done().
  • Die Pull-Funktion empfängt Werte von c und gibt sie aus. Es signalisiert auch den Abschluss mit wg.Done().

Das Problem liegt darin, wie die WaitGroup an die Goroutinen übergeben wird. Wenn ein Wert ohne kaufmännisches Und (&) übergeben wird, wird er als Wert und nicht als Referenz übergeben. In diesem Fall wird für jede Goroutine eine Kopie der WaitGroup erstellt.

Wenn daher jede Goroutine wg.Done() aufruft, ändert sie ihre lokale Kopie der WaitGroup. Da der Hauptthread wartet, bis wg angibt, dass alle Goroutinen abgeschlossen sind, wartet er auf unbestimmte Zeit, da keine der Goroutinen die ursprüngliche WaitGroup aktualisiert. Dies führt zu einem Deadlock.

Um dieses Problem zu beheben, müssen wir die WaitGroup als Referenz übergeben. Dadurch wird sichergestellt, dass beide Goroutinen dieselbe Instanz der WaitGroup ändern und ihre Fertigstellung dem Hauptthread korrekt signalisieren.

Hier ist eine überarbeitete Version des Codes mit der Korrektur:

<br>Pakethauptseite</p>
<p>import (</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"fmt"
"sync"
Nach dem Login kopieren
Nach dem Login kopieren

)

func push(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
Nach dem Login kopieren
Nach dem Login kopieren

}

func pull(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
Nach dem Login kopieren
Nach dem Login kopieren

}

func main() {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, &wg) // Pass the WaitGroup by reference using the ampersand
go pull(c, &wg) // Pass the WaitGroup by reference using the ampersand

wg.Wait()
Nach dem Login kopieren

}

Durch die Übergabe der WaitGroup als Referenz stellen wir sicher, dass der Hauptthread korrekt bestimmen kann, wann beide Goroutinen ihre Aufgaben abgeschlossen haben, und vermeiden so den Deadlock.

Das obige ist der detaillierte Inhalt vonWarum führt die Übergabe einer WaitGroup als Wert in Go zu einem Deadlock und wie kann dieser behoben werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Vorheriger Artikel:Wie kann ich Funktionsaufrufe als Argumente in Go übergeben? Nächster Artikel:So stellen Sie Go-Webanwendungen auf IIS bereit: Eine Schritt-für-Schritt-Anleitung mit HttpPlatformHandler?
Erklärung dieser Website
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
Neueste Artikel des Autors
Aktuelle Ausgaben
verwandte Themen
Mehr>
Beliebte Empfehlungen
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage