Heim >Backend-Entwicklung >Golang >Warum bleibt eine Go „select'-Anweisung ohne einen „default'-Fall hängen und wie kann das behoben werden?

Warum bleibt eine Go „select'-Anweisung ohne einen „default'-Fall hängen und wie kann das behoben werden?

Barbara Streisand
Barbara StreisandOriginal
2024-11-24 06:31:15304Durchsuche

Why Does a Go `select` Statement Hang Without a `default` Case and How Can It Be Fixed?

Goroutine mit Select stoppt nicht ohne fmt.Print()

Problem:

In der Go-Tour-Übung #71: Die Verwendung von go run 71_hang.go nogood führt dazu, dass das Programm auf unbestimmte Zeit läuft, während go run 71_hang.go ok wie folgt funktioniert erwartet. Der einzige Unterschied besteht im Hinzufügen von fmt.Print("") im Standardfall der Select-Anweisung.

Erklärung:

Eine Standardanweisung in einer Select-Anweisung ändert sich das Verhalten der Aussage. Ohne Vorgabe wählen Sie Blöcke aus, bis Nachrichten auf den Kanälen vorhanden sind. Bei einer Standardeinstellung führt select die Standardanweisung jedes Mal aus, wenn von den Kanälen nichts zu lesen ist.

Im Originalcode erstellt die Standardanweisung eine Endlosschleife. Da der Scheduler keine anderen Goroutinen einplanen kann, läuft das Programm auf unbestimmte Zeit.

Lösung 1:

Entfernen Sie die Standardanweisung und verwenden Sie eine nicht blockierende Auswahl:

for {
    select {
        case todo := <-toDoList:
            if todo.depth > 0 && !visited[todo.url] {
                crawling++
                visited[todo.url] = true
                go crawl(todo, fetcher, toDoList, doneCrawling)
            }
        case <-doneCrawling:
            crawling--
    }
    if crawling == 0 {
        break
    }
}

Lösung 2:

Behalten die Standardanweisung, aber stellen Sie sicher, dass die Goroutine nachgibt. Eine Möglichkeit, dies zu erreichen, ist die Verwendung von GOMAXPROCS=2, wodurch der Scheduler mehrere Kerne verwenden kann.

Zusätzlicher Hinweis:

Goroutinen werden kooperativ geplant. Select ist ein Punkt, an dem eine Goroutine nachgeben sollte. Im gegebenen Beispiel ist jedoch der Grund, warum „select“ ohne die Anweisung „fmt.Print()“ nicht ausgibt, nicht vollständig geklärt und erfordert weitere Untersuchungen.

Das obige ist der detaillierte Inhalt vonWarum bleibt eine Go „select'-Anweisung ohne einen „default'-Fall hängen und wie kann das behoben werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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