Heim > Backend-Entwicklung > Golang > Detaillierte Erklärung des Golang-Kanals Chan

Detaillierte Erklärung des Golang-Kanals Chan

藏色散人
Freigeben: 2020-11-09 15:40:54
nach vorne
2629 Leute haben es durchsucht

Die Kolumne Golang-Tutorial stellt Ihnen Golang über den Kanal Chan vor. Ich hoffe, dass sie Freunden, die es brauchen, hilfreich sein wird!

Detaillierte Erklärung des Golang-Kanals Chan

Schauen wir uns zunächst Threads an, die auf Golang auch Goroutine genannt werden.

Bevor wir diesen Artikel lesen, müssen wir Parallelität und Parallelität verstehen. Golangs Thread ist ein Parallelitätsmechanismus, keine Parallelität. Sie können im Internet nach den Unterschieden suchen. Es gibt viele Einführungen online.

Schauen wir uns zuerst ein Beispiel an

import(
         "fmt"
)

funcmain(){

    go fmt.Println("1")
    fmt.Println("2")    
}
Nach dem Login kopieren

In Golang können Sie einen Thread erstellen, indem Sie das Schlüsselwort go gefolgt von einer Funktion verwenden. Die letztere Funktion kann eine vorab geschriebene Funktion oder eine anonyme Funktion sein. Der obige Code erstellt eine anonyme Funktion und übergibt außerdem einen Parameter i. Das i in Klammern unten ist der tatsächliche Parameter a ein formaler Parameter.

Kann der obige Code also wie erwartet 1, 2 und 3 ausgeben? Ich sage Ihnen, nein, das Programm kann nur 2 ausdrucken. Ich werde unten den richtigen Code veröffentlichen

funcmain(){    var i=3    go func(a int) {        fmt.Println(a)
        fmt.Println("1")
    }(i)
    fmt.Println("2")}
Nach dem Login kopieren

Ich habe am Ende nur eine Codezeile hinzugefügt, um den Hauptthread eine Sekunde lang in den Ruhezustand zu versetzen, und das Programm druckt nacheinander 2, 3 und 1 aus.

Warum passiert das also? Da das Programm zuerst den Hauptthread ausführt, wird das Programm nach Abschluss der Ausführung des Hauptthreads sofort beendet, sodass keine zusätzliche Zeit für die Ausführung des untergeordneten Threads verbleibt. Wenn Sie den Hauptthread am Ende des Programms 1 Sekunde lang ruhen lassen, hat das Programm genügend Zeit, den untergeordneten Thread auszuführen.

Der Thread endet hier, werfen wir einen Blick auf den Kanal.

Kanal wird auch Kanal genannt. Wie der Name schon sagt, besteht die Funktion des Kanals darin, Daten zwischen mehreren Threads zu übertragen.

Erstelle einen ungepufferten Kanal

chreadandwrite :=make(chan int)

chonlyread := make(<-chan int) //Erstelle einen schreibgeschützten Kanal

chonlywrite := make(chan<- int) // Erstellen Sie einen schreibgeschützten Kanal. Schreibkanal.

Schauen wir uns ein Beispiel an:

import(    "fmt"
    "time"    )funcmain(){    var i = 3    go func(a int) {        fmt.Println(a)
        fmt.Println("1")
    }(i)
    fmt.Println("2")
    time.Sleep(1 * time.Second)}
Nach dem Login kopieren

Bei der Ausführung dieses Codes tritt ein Fehler auf: Schwerwiegender Fehler: Alle Goroutinen schlafen – Deadlock!


Dieser Fehler bedeutet, dass der Thread gefallen ist in einen Deadlock geraten und das Programm kann nicht weiter ausgeführt werden. Was ist also die Ursache für diesen Fehler?

Wir haben einen ungepufferten Kanal erstellt und ihm dann einen Wert zugewiesen. Das Programm geriet nach Abschluss der Zuweisung in einen Deadlock. Da unser Kanal ungepuffert, also synchron, ist, wird das Programm blockiert, bevor der Kanal nach Abschluss der Zuweisung gelesen werden kann. Hier ist ein sehr wichtiges Konzept: Der Kanalmechanismus ist First-In-First-Out. Wenn Sie dem Kanal einen Wert zuweisen, muss dieser gelesen werden, da dies sonst zu einer Blockierung führt. Dies gilt natürlich nur für ungepufferte Kanäle . Bei gepufferten Kanälen blockiert der Sender, bis die Daten in den Puffer kopiert wurden. Wenn der Puffer voll ist, kann der Sender den Blockierungszustand erst wieder aufheben, nachdem der Empfänger die Daten entfernt hat.

Für das obige Beispiel gibt es zwei Lösungen:

1. Fügen Sie dem Kanal einen Puffer hinzu und lassen Sie den Hauptthread am Ende des Programms wie folgt:

    ch :=make(chan int)     
    ch <- 1
      go func() {
        <-ch
        fmt.Println("1")
      }()
      fmt.Println("2")
Nach dem Login kopieren

In diesem Fall In diesem Fall gibt das Programm 1, 2

2 aus. Fügen Sie die Codezeile ch<-1 hinter den Sub-Thread-Code ein. Der Code lautet wie folgt:

    ch :=make(chan int,1)
    ch <- 1
    go func() {
        v := <-ch
        fmt.Println(v)
    }()
    time.Sleep(1 * time.Second)
    fmt.Println("2")
Nach dem Login kopieren

Der Haupt-Thread muss hier nicht ruhen , denn nachdem der Kanal im Hauptthread zugewiesen wurde, wird der Hauptthread blockiert, bis der Wert des Kanals im untergeordneten Thread abgerufen wird.

Schauen wir uns abschließend ein Beispiel für einen Produzenten und einen Konsumenten an:

    ch :=make(chan int)    go func() {
        v := <-ch
        fmt.Println(v)
    }()
    ch <- 1
    fmt.Println("2")
Nach dem Login kopieren

Da der Kanal in diesem Code nicht gepuffert ist, blockiert der Produzenten-Thread, bis der Konsumenten-Thread annimmt, wenn der Produzent dem Kanal einen Wert zuweist die Daten aus dem Kanal aus. Nachdem der Verbraucher die Daten zum ersten Mal entnommen hat, wird der Thread des Verbrauchers auch im nächsten Zyklus blockiert, da der Produzent die Daten noch nicht gespeichert hat. Zu diesem Zeitpunkt führt das Programm den Thread des Produzenten aus. Auf diese Weise wechselt das Programm kontinuierlich zwischen den Consumer- und Producer-Threads, bis die Schleife endet.

Sehen wir uns ein weiteres Beispiel mit Pufferung an:

import (    "fmt"
    "time")func produce(p chan<- int) {    for i := 0; i < 10; i++ {
        p <- i
        fmt.Println("send:", i)
    }
}func consumer(c <-chan int) {    for i := 0; i < 10; i++ {
        v := <-c
        fmt.Println("receive:", v)
    }
}func main() {
    ch := make(chan int)    go produce(ch)    go consumer(ch)
    time.Sleep(1 * time.Second)
}
Nach dem Login kopieren
In diesem Programm kann der Puffer 10 Ganzzahlen vom Typ int speichern, der Thread wird nicht blockiert und es werden 10 Ganzzahlen gleichzeitig gespeichert Die Ganzzahl wird im Kanal gespeichert und beim Lesen auch auf einmal gelesen.

Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung des Golang-Kanals Chan. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:csdn.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage