Maison > développement back-end > Golang > le corps du texte

Impasse - toutes les goroutines dorment (même en utilisant des groupes d'attente)

PHPz
Libérer: 2024-02-09 13:40:08
avant
1146 Les gens l'ont consulté

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

L'éditeur PHP Xiaoxin est là pour vous présenter un problème courant de programmation simultanée : une impasse. Le blocage signifie que toutes les goroutines sont entrées en état de veille et ne peuvent pas continuer à s'exécuter même si des mécanismes tels que des groupes d'attente sont utilisés. Dans ce cas, toutes les goroutines sont incapables d’avancer, ce qui fait tomber le programme dans un état d’attente infinie. En programmation simultanée, il est très important d’éviter les blocages, et nous devons comprendre ses causes et ses solutions pour assurer le fonctionnement normal du programme.

Contenu de la question

J'apprends la simultanéité Go et je souhaite que deux routines Go continuent à communiquer entre elles tout en transmettant les valeurs mises à jour via un canal. L’un ajoute 2 et l’autre soustrait 1. Le code et le résultat sont les suivants :

Qu'est-ce qui ne va pas avec ce code ?

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

}
Copier après la connexion

Sortie :

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()
Copier après la connexion

Puis il s'arrête.

Pourquoi la goroutine n'échange-t-elle pas toujours les valeurs même si je n'appelle pas wg.done() dans la goroutine ?

Solution de contournement

Les deux goroutines que vous démarrez reçoivent simplement une valeur et envoient une valeur, puis se terminent. A partir de là, c'est juste main goroutine,在 wg.wait() 处被阻止,因为你从未调用 wg.done().

Vous avez oublié d'utiliser la boucle (n infinie) :

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
    }
}
Copier après la connexion

Avec ce changement, votre application s'exécutera pour toujours et le résultat sera :

AT Recieved:  1
SO Recieved:  3
AT Recieved:  2
SO Recieved:  4
AT Recieved:  3
SO Recieved:  5
AT Recieved:  4
....
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal