Deadlock – alle Goroutinen schlafen (sogar bei Verwendung von Wartegruppen)

PHPz
Freigeben: 2024-02-09 13:40:08
nach vorne
1146 Leute haben es durchsucht

死锁 - 所有 goroutine 都处于睡眠状态(即使使用等待组)

Der PHP-Editor Xiaoxin ist hier, um Ihnen einen häufigen Deadlock bei gleichzeitigen Programmierproblemen vorzustellen. Deadlock bedeutet, dass alle Goroutinen in den Ruhezustand übergegangen sind und nicht weiter ausgeführt werden können, selbst wenn Mechanismen wie Wartegruppen verwendet werden. In diesem Fall können nicht alle Goroutinen vorwärts gehen, was dazu führt, dass das Programm in einen unendlichen Wartezustand fällt. Bei der gleichzeitigen Programmierung ist es sehr wichtig, Deadlocks zu vermeiden, und wir müssen seine Ursachen und Lösungen verstehen, um den normalen Betrieb des Programms sicherzustellen.

Frageninhalt

Ich lerne Go-Parallelität und möchte, dass zwei Go-Routinen weiterhin miteinander kommunizieren und gleichzeitig aktualisierte Werte über einen Kanal weitergeben. Einer addiert 2 und der andere subtrahiert 1. Der Code und die Ausgabe lauten wie folgt:

Was stimmt mit diesem Code nicht?

package main

import (
    "fmt"
    "sync"
    "time"
)

var wg sync.waitgroup

func addtwo(r chan int, e chan int) {
    val := <-r
    fmt.println("at recieved: ", val)
    time.sleep(1 * time.second)
    e <- val + 2
}

func subtractone(r chan int, e chan int) {
    val := <-r
    fmt.println("so recieved: ", val)
    time.sleep(1 * time.second)
    e <- val - 1
}

func main() {
    ch := make(chan int)
    ch2 := make(chan int)

    wg.add(1)
    go addtwo(ch, ch2)

    wg.add(1)
    go subtractone(ch2, ch)

    ch <- 1
    wg.wait()

}
Nach dem Login kopieren

Ausgabe:

AT Recieved:  1
SO Recieved:  3
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x4b2de8?)
    /usr/lib/go-1.18/src/runtime/sema.go:56 +0x25
sync.(*WaitGroup).Wait(0x0?)
    /usr/lib/go-1.18/src/sync/waitgroup.go:136 +0x52
main.main()
Nach dem Login kopieren

Dann hört es auf.

Warum tauscht die Goroutine nicht immer Werte aus, auch wenn ich wg.done() in der Goroutine nicht aufrufe?

Workaround

Beide Goroutinen, die Sie starten, empfangen einfach einen Wert, senden einen Wert und enden dann. Von da an ist es nur noch main goroutine,在 wg.wait() 处被阻止,因为你从未调用 wg.done().

Sie haben vergessen, eine (n Endlos-)Schleife zu verwenden:

func addtwo(r chan int, e chan int) {
    for {
        val := <-r
        fmt.println("at recieved: ", val)
        time.sleep(1 * time.second)
        e <- val + 2
    }
}

func subtractone(r chan int, e chan int) {
    for {
        val := <-r
        fmt.println("so recieved: ", val)
        time.sleep(1 * time.second)
        e <- val - 1
    }
}
Nach dem Login kopieren

Mit dieser Änderung läuft Ihre Anwendung für immer und die Ausgabe lautet:

AT Recieved:  1
SO Recieved:  3
AT Recieved:  2
SO Recieved:  4
AT Recieved:  3
SO Recieved:  5
AT Recieved:  4
....
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonDeadlock – alle Goroutinen schlafen (sogar bei Verwendung von Wartegruppen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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