Maison  >  Article  >  développement back-end  >  Comment implémenter plusieurs coroutines pour lire et écrire les mêmes canaux en même temps dans Golang

Comment implémenter plusieurs coroutines pour lire et écrire les mêmes canaux en même temps dans Golang

WBOY
WBOYoriginal
2023-08-07 14:25:061822parcourir

Comment implémenter plusieurs coroutines pour lire et écrire les mêmes canaux en même temps dans Golang

Dans la programmation Go, les goroutines sont largement utilisées pour obtenir la concurrence et le parallélisme. Les canaux sont une structure de données spéciale utilisée pour la communication et la synchronisation entre les coroutines. Les canaux offrent un moyen sûr de partager des données entre coroutines.

Dans certains cas, nous pouvons avoir besoin de plusieurs coroutines pour lire ou écrire le même canal en même temps. Étant donné que Channel se bloque par défaut, si des mesures spéciales ne sont pas prises, plusieurs coroutines se bloqueront mutuellement, empêchant le programme de fonctionner normalement. Ensuite, je couvrirai deux solutions courantes.

Solution 1 : Utiliser un canal tamponné

Le canal tamponné est un canal à capacité limitée. Lors de la création d'un Channel, nous pouvons préciser sa capacité. Lorsque le tampon du canal n'est pas plein, les opérations d'écriture peuvent se terminer immédiatement ; lorsque le tampon n'est pas vide, les opérations de lecture peuvent également se terminer immédiatement. Les opérations de lecture et d'écriture se bloquent uniquement lorsque le tampon est plein ou vide.

Ce qui suit est un exemple de code :

package main

import (
    "fmt"
    "time"
)

func main() {
    // 创建一个容量为1的缓冲 Channel
    ch := make(chan int, 1)

    // 启动多个协程,并同时写入 Channel
    for i := 1; i <= 5; i++ {
        go func(i int) {
            ch <- i
            fmt.Printf("协程 %d 写入数据
", i)
        }(i)
    }

    // 读取 Channel 中的数据
    time.Sleep(time.Second) // 休眠 1 秒,等待协程写入数据
    for i := 1; i <= 5; i++ {
        fmt.Printf("读取到数据:%d
", <-ch)
    }
}

Dans le code ci-dessus, nous créons un canal tampon ch d'une capacité de 1. Ensuite, 5 coroutines sont démarrées et écrivent des données sur le canal ch en même temps. Étant donné que le canal est mis en mémoire tampon, les écritures se terminent immédiatement. Enfin, nous parcourons les données du canal et effectuons des opérations de lecture. ch。然后启动了 5 个协程,它们同时向 Channel ch 写入数据。由于 Channel 是缓冲的,所以写入操作可以立即完成。最后,我们遍历 Channel 中的数据,并进行读取操作。

解决方案二:使用带有 select 语句的无缓冲 Channel

无缓冲 Channel 是一种没有容量的 Channel。在这种情况下,读取和写入操作都会阻塞,直到有另一个协程执行相反的操作。但我们可以使用 select 语句来实现同时读写无缓冲 Channel,避免协程相互阻塞。

下面是一个示例代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    // 创建无缓冲 Channel
    ch := make(chan int)

    // 启动多个协程,并同时写入 Channel
    for i := 1; i <= 5; i++ {
        go func(i int) {
            select {
            case ch <- i:
                fmt.Printf("协程 %d 写入数据
", i)
            default:
                fmt.Printf("协程 %d 无法写入数据
", i)
            }
        }(i)
    }

    // 读取 Channel 中的数据
    time.Sleep(time.Second) // 休眠 1 秒,等待协程写入数据
    for i := 1; i <= 5; i++ {
        select {
        case data := <-ch:
            fmt.Printf("读取到数据:%d
", data)
        default:
            fmt.Println("无法读取数据")
        }
    }
}

上述代码中,我们创建了一个无缓冲 Channel ch。与解决方案一不同的是,在写入数据时我们使用了 select 语句,并在 case 中处理写入成功和失败的情况。相同地,在读取数据时我们也使用了 select

Solution 2 : utilisez un canal sans tampon avec une instruction select

Un canal sans tampon est un canal sans capacité. Dans ce cas, les opérations de lecture et d’écriture se bloquent jusqu’à ce qu’une autre coroutine effectue l’opération inverse. Mais nous pouvons utiliser l'instruction select pour lire et écrire simultanément un canal sans tampon afin d'éviter que les coroutines ne se bloquent mutuellement.

Voici un exemple de code :

rrreee

Dans le code ci-dessus, nous créons un canal ch sans tampon. La différence avec la première solution est que nous utilisons l'instruction select lors de l'écriture des données et gérons le succès et l'échec de l'écriture dans case. De même, nous utilisons également l'instruction select lors de la lecture de données pour gérer la situation dans laquelle les données ne peuvent pas être lues. 🎜🎜Résumé : 🎜🎜En utilisant un canal tamponné ou un canal non tamponné avec une instruction select, nous pouvons obtenir plusieurs coroutines lisant et écrivant le même canal en même temps. Ces solutions peuvent améliorer l'efficacité de votre programme et éviter que les coroutines ne se bloquent les unes les autres. 🎜🎜Bien sûr, en plus des solutions ci-dessus, il existe d'autres techniques de programmation simultanée plus avancées, comme l'utilisation de WaitGroup, Mutex, etc. Dans les applications réelles, nous devons choisir un mécanisme de contrôle de concurrence approprié en fonction de besoins spécifiques. J'espère que cet article pourra vous aider à mieux comprendre et appliquer la programmation simultanée dans Golang. 🎜

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