Was sind die Ursachen für Deadlocks im Go-Code, der WaitGroups und Buffered Channels verwendet?

PHPz
Freigeben: 2024-02-09 11:09:30
nach vorne
752 Leute haben es durchsucht

使用 WaitGroups 和 Buffered Channels 的 Go 代码中出现死锁的原因是什么?

php-Editor Baicao beantwortet in diesem Artikel eine häufig gestellte Frage: „Was ist der Grund für einen Deadlock im Go-Code mit WaitGroups und Buffered Channels?“ In der Go-Sprache sind WaitGroups und Buffered Channels häufig verwendete Tools für die gleichzeitige Programmierung. Manchmal kann es jedoch im Code, der sie verwendet, zu Deadlock-Situationen kommen. In diesem Artikel werden die Ursachen von Deadlocks untersucht und Lösungen bereitgestellt, die den Lesern helfen, dieses Problem zu vermeiden. Egal, ob Sie Anfänger oder erfahrener Go-Entwickler sind, dieser Artikel liefert Ihnen wertvolle Informationen.

Frageninhalt

Wartegruppen, Pufferkanäle und Deadlocks

Dieser Code von mir verursacht einen Deadlock, aber ich bin mir nicht sicher, warum. Ich habe versucht, Mutexe an verschiedenen Stellen zu verwenden und Kanäle innerhalb und außerhalb separater Go-Routinen zu schließen, aber immer noch das gleiche Ergebnis.

Ich versuche, Daten über einen Kanal (Inputchan) zu senden und dann Daten von einem anderen Kanal (Outputchan) zu lesen

package main

import (
    "fmt"
    "sync"
)

func listStuff(wg *sync.WaitGroup, workerID int, inputChan chan int, outputChan chan int) {
    defer wg.Done()

    for i := range inputChan {
        fmt.Println("sending ", i)
        outputChan <- i
    }
}

func List(workers int) ([]int, error) {
    _output := make([]int, 0)

    inputChan := make(chan int, 1000)
    outputChan := make(chan int, 1000)

    var wg sync.WaitGroup
    wg.Add(workers)

    fmt.Printf("+++ Spinning up %v workers\n", workers)
    for i := 0; i < workers; i++ {
        go listStuff(&wg, i, inputChan, outputChan)
    }

    for i := 0; i < 3000; i++ {
        inputChan <- i
    }

    done := make(chan struct{})
    go func() {
        close(done)
        close(inputChan)
        close(outputChan)
        wg.Wait()
    }()

    for o := range outputChan {
        fmt.Println("reading from channel...")
        _output = append(_output, o)
    }

    <-done
    fmt.Printf("+++ output len: %v\n", len(_output))
    return _output, nil
}

func main() {
    List(5)
}
Nach dem Login kopieren

Workaround

Der Code in der Hauptfunktion ist kontinuierlich, Zuerstversuchen Sie, 3k Werte in inputchan zu schreiben inputchan 然后将从 outputchanDann

liest die Werte aus outputchan</ Code>. <p> </p>Ihr Code blockiert den ersten Schritt: <ul> <li> <code>inputchan 之前,outputchan 不会流失任何内容,因此工作人员最终会在第一个 1k 值之后卡在 outputchan <- iDer Wert von 3.000 wurde erfolgreich an
  • gesendet inputchan 中消耗资源,main 将在大约 2k 个值之后卡在 inputchan <- iSobald das Personal aufhört
  • inputchan <- i) 和最终消费者 (for o := range outputchan {Eine Möglichkeit, dieses Problem zu lösen, besteht darin, den Produzenten (

    ) in einer separaten Goroutine laufen zu lassen.

    Sie können einen dieser Schauspieler in der Haupt-Goroutine behalten und einen neuen Schauspieler für den anderen einsetzen. Zum Beispiel:

    go func(inputchan chan<- int){
        for i := 0; i < 3000; i++ {
            inputchan <- i
        }
        close(inputchan)
    }(inputchan)
    
    done := make(chan struct{})
    go func() {
        close(done)
        // close(inputchan) // i chose to close inputchan above, don't close it twice
        close(outputchan)
        wg.wait()
    }()
    
    ...
    Nach dem Login kopieren
    https://www.php.cn/link/80e4c54699b5b8cf8c67dd496909fceb

    done 的操作顺序很重要;通道 doneoutputchan 只能在 wg.done()Eine zusätzliche Anmerkung: Surround-Signalisierung , um alle Mitarbeiter anzuweisen, zu schließen, wenn sie fertig sind

    🎜
    // it is best to close inputChan next to the code that controls
        // when its input is complete.
        close(inputChan)
        // If you had several producers writing to the same channel, you
        // would probably have to add a separate waitgroup to handle closing,
        // much like you did for your workers
    
        go func() {
            wg.Wait()
            // the two following actions must happen *after* workers have
            // completed
            close(done)
            close(outputChan)
        }()
    Nach dem Login kopieren

    Das obige ist der detaillierte Inhalt vonWas sind die Ursachen für Deadlocks im Go-Code, der WaitGroups und Buffered Channels verwendet?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Verwandte Etiketten:
    Quelle:stackoverflow.com
    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
    Beliebte Tutorials
    Mehr>
    Neueste Downloads
    Mehr>
    Web-Effekte
    Quellcode der Website
    Website-Materialien
    Frontend-Vorlage