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

Pourquoi la limite de tampon de Go Channel n'écrit/lit-elle pas correctement ?

WBOY
Libérer: 2024-02-09 10:30:19
avant
422 Les gens l'ont consulté

为什么Go Channel的缓冲区不能正确限制写入/读取?

l'éditeur php Youzi répondra à une question courante dans cet article : "Pourquoi le buffer de Go Channel ne limite-t-il pas correctement l'écriture/lecture ?" Lorsque nous utilisons un Channel avec un buffer, nous espérons pouvoir contrôler le comportement du programme en limitant le nombre d'opérations d'écriture ou de lecture. Cependant, en fait, le tampon Channel ne peut pas limiter directement le nombre d'opérations d'écriture/lecture. Les causes et les solutions à ce problème seront détaillées ci-dessous.

Contenu de la question

J'essaie de communiquer entre deux routines de go en utilisant des canaux. Tout d’abord, j’ai créé le canal entier, puis je l’ai passé comme paramètre à une routine go qui imprime une séquence de nombres de 0 à 10. Le résultat de ces programmes n’a aucun sens.

Voici le code principal :

func worker(identifier string, ch chan<- int) {
    fmt.printf("entering worker %s\n", identifier)
    for i := 0; i < 10; i++ {
        fmt.printf("writing %d\n", i)
        ch <- i
    }

    fmt.printf("exiting worker %s\n", identifier)

    close(ch)
}

func main() {
    ch := make(chan int)
    go worker("1", ch)

    for v := range ch {
        fmt.printf("reading %d\n", v)
    }
}
Copier après la connexion

Pour cette exécution de code, j'ai obtenu le résultat suivant :

entering worker 1
writing 0
writing 1
reading 0
reading 1
writing 2
writing 3
reading 2
reading 3
writing 4
writing 5
reading 4
reading 5
writing 6
writing 7
reading 6
reading 7
writing 8
writing 9
reading 8
reading 9
exiting worker 1
Copier après la connexion

Notez qu'il y a deux exécutions en écriture suivies de deux exécutions en lecture.

Plus tard, j'ai défini une taille de tampon pour réaliser les fonctions suivantes :

func main() {
    ch := make(chan int, 3) // <= buffer
    go worker("1", ch)

    for v := range ch {
        fmt.printf("reading %d\n", v)
    }

}
Copier après la connexion

Ensuite, nous obtenons le résultat suivant :

Entering worker 1
Writing 0
Writing 1
Writing 2
Writing 3
Writing 4
Reading 0
Reading 1
Reading 2
Reading 3
Reading 4
Writing 5
Writing 6
Writing 7
Writing 8
Writing 9
Reading 5
Reading 6
Reading 7
Reading 8
Reading 9
Exiting worker 1
Copier après la connexion

Notez que nous avons maintenant 5 exécutions en écriture puis 5 exécutions en lecture.

Une fois que nous avons le code et le résultat, la dernière question se pose : pourquoi ces exécutions se comportent-elles comme elles le font ? Premièrement, n'est-il pas censé lire et écrire un seul chiffre à la fois ? Au-delà de cela, pourquoi la deuxième exécution lit-elle et écrit-elle 5 nombres à chaque fois au lieu de 3 (puisque c'est la taille du tampon) ?

Solution de contournement

Vous êtes confus lors de l'impression de messages et lors de la lecture ou de l'écriture de chiffres à partir de la chaîne.

Lorsqu'une écriture se produit, aucun message « écriture » n'apparaît. Ils se produisent à un moment donné entre les écritures. De même, le message « lecture » apparaît à un moment donné entre les lectures.

Voici une façon d'organiser le premier extrait de code, qui produit le résultat affiché :

  • Essayez principalement de lire, puis bloquez.
  • Le personnel imprime « Écriture 0 ».
  • Worker écrit 0 et principal lit.
  • L'ouvrier imprime "Ecriture 1".
  • Le thread de travail a tenté d'écrire 1, mais a été bloqué.
  • Imprimez principalement "Lecture 0".
  • Le contenu principal est 1.
  • Impression principale « Lecture 1 ».
  • Essayez principalement de lire, puis bloquez.

Le contrôle est constamment transmis entre main et Worker comme ceci, chacun imprimant 2 messages avant de bloquer.

De même, votre deuxième clip peut être organisé comme ceci :

  • Essayez principalement de lire, puis bloquez.
  • Worker imprime "Writing 0" et envoie 0 directement au main.
  • Worker imprime "Writing 1" et tamponne 1.
  • Worker imprime "Writing 2" et met en mémoire tampon 2.
  • Worker imprime "Writing 3" et tamponne 3.
  • Le fil de travail imprime "Writing 4" et bloque les tentatives d'envoi de 4.
  • main termine la lecture bloquée et imprime "Lecture 0".
  • main lit le 1 tamponné et imprime "Lecture 1".
  • main lit le 2 tamponné et imprime "Lecture 2".
  • main lit le 3 tamponné et imprime "Lecture 3".
  • main lit Worker bloqué 4 et imprime "Lecture 4".
  • Essayez principalement de lire, puis bloquez.
  • L'exécution revient au travailleur...

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!

Étiquettes associées:
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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!