Le canal en langage Go est une structure de données très utile. Il peut réaliser le partage et la synchronisation de données en programmation simultanée, et il est très efficace. Cependant, il y a une chose qui nécessite une attention particulière lors de l'utilisation des canaux, et c'est aussi une erreur que de nombreux débutants en langage Go commettent souvent, c'est-à-dire que chan ne peut pas bloquer.
Dans le langage Go, la transmission de données et la synchronisation entre plusieurs goroutines peuvent être réalisées via des canaux, évitant ainsi les verrous de synchronisation encombrants et les inévitables problèmes de blocage. Lorsque nous utilisons des canaux pour envoyer et recevoir des données entre deux ou plusieurs goroutines, nous utilisons souvent le code suivant :
ch := make(chan int) go func() { ch <- 1 }() value := <-ch fmt.Println(value)
Dans ce code, nous créons un canal de type int et l'utilisons dans un nouveau Un entier 1 est envoyé au canal dans la goroutine. Ensuite, appelez <-ch
dans la goroutine principale pour accepter les données dans le canal et les imprimer. Cet exemple est simple, mais il montre l'utilisation de canaux pour synchroniser les données entre deux goroutines.
Dans le code ci-dessus, nous pouvons constater que ce canal n'est pas explicitement fermé et qu'il n'est pas mis en cache. Alors, dans ce cas, que se passe-t-il lorsque nous lisons un canal non fermé et non mis en cache ?
Dans ce cas, si le canal est vide, alors nous bloquerons lors de sa lecture jusqu'à ce qu'une goroutine écrive une nouvelle valeur ou ferme le canal. Cependant, si la chaîne reste vide, notre programme sera bloqué définitivement. Il s'agit d'une situation très dangereuse qui conduit souvent à des blocages et à d'autres problèmes dans les programmes dans les applications pratiques.
Alors, comment pouvons-nous éviter cela ? C'est en fait très simple, il suffit de s'assurer que la chaîne ne se bloque pas lors de son utilisation. Tant que nous pouvons garantir que le canal ne restera pas vide lors de son utilisation, nous pouvons éviter les problèmes de blocage.
Une méthode courante consiste à déterminer si l'état du canal suivant est vide avant que goroutine n'écrive la valeur, ou à lui donner une capacité lors de la mise en cache du canal pour garantir que l'écriture de la valeur ne provoquera pas de blocage. Par exemple, dans l'exemple suivant nous utilisons un canal en cache :
ch := make(chan int, 1) ch <- 1 value := <-ch fmt.Println(value)
Ici, nous précisons une capacité de 1 lors de la création du canal, donc après avoir écrit une valeur, même si nous ne lisons pas la valeur immédiatement, le programme ne le fera toujours pas. être bloqué. Cela évite les problèmes mentionnés ci-dessus.
En plus d'utiliser les canaux mis en cache pour éviter le blocage, nous pouvons également utiliser des instructions select pour gérer les opérations de lecture et d'écriture des canaux. L'instruction select peut surveiller plusieurs canaux en même temps. Une fois que l'un des canaux reçoit une valeur, l'opération correspondante sera effectuée immédiatement. Prenons l'exemple suivant :
ch := make(chan int) timer := time.NewTicker(time.Second) select { case ch <- 1: fmt.Println("value sent") case <-timer.C: fmt.Println("timeout") }
Ici, nous créons un nouveau Ticker qui se déclenche toutes les secondes. Ensuite, nous écoutons deux canaux dans l'instruction select. Si ch peut être écrit, "value sent" est affiché, sinon "timeout" est affiché après une seconde.
En résumé, bien que le canal soit une structure de données très utile, des précautions particulières doivent être prises lors de son utilisation pour éviter le blocage. Tant que nous pouvons nous assurer que le canal ne se bloque pas lors de son utilisation, nous pouvons utiliser pleinement cet outil pour réaliser une programmation simultanée efficace.
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!