Maison  >  Article  >  développement back-end  >  Impasse - toutes les goroutines dorment (même en utilisant des groupes d'attente)

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

PHPz
PHPzavant
2024-02-09 13:40:081112parcourir

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

}

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

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

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

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer