Heim  >  Artikel  >  Backend-Entwicklung  >  Deadlock – alle Goroutinen schlafen (sogar bei Verwendung von Wartegruppen)

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

PHPz
PHPznach vorne
2024-02-09 13:40:081114Durchsuche

死锁 - 所有 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()

}

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()

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
    }
}

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
....

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen