Schreiben Sie Chan in die sync.WaitGroup-Goroutine
Der PHP-Editor Yuzi wird eine Methode zum Schreiben von Chan in der sync.WaitGroup-Goroutine vorstellen. Bei der gleichzeitigen Programmierung ist sync.WaitGroup ein sehr nützlicher Synchronisationsmechanismus, der auf den Abschluss der Ausführung einer Gruppe von Goroutinen warten kann. Manchmal müssen wir jedoch die Ergebnisse in einen Kanal schreiben, nachdem die Goroutine die Ausführung abgeschlossen hat, damit sie von anderen Goroutinen genutzt werden können. In diesem Artikel wird detailliert beschrieben, wie diese Funktion in der sync.WaitGroup-Goroutine implementiert wird. Werfen wir einen Blick darauf!
Frageninhalt
Ich erhalte eine Liste mit Elementen von einem API-Endpunkt. Dann stelle ich für jedes Projekt eine weitere API-Anfrage, um Daten über das einzelne Projekt zu erhalten.
Ich kann nicht gleichzeitig eine zweite API-Anfrage an jedes Projekt stellen, da die Rate meines API-Tokens begrenzt ist und ich gedrosselt werde, wenn ich zu viele Anfragen gleichzeitig stelle.
Allerdings können die anfänglichen API-Antwortdaten in mehrere Seiten aufgeteilt werden, sodass ich Seiten mit Daten gleichzeitig verarbeiten kann.
Nach einiger Recherche macht der folgende Code genau das, was ich will:
func main() { // pretend paginated results from initial API request page1 := []int{1, 2, 3} page2 := []int{4, 5, 6} page3 := []int{7, 8, 9} pages := [][]int{page1, page2, page3} results := make(chan string) var wg sync.WaitGroup for i := range pages { wg.Add(1) go func(i int) { defer wg.Done() for j := range pages[i] { // simulate making additional API request and building the report time.Sleep(500 * time.Millisecond) result := fmt.Sprintf("Finished creating report for %d", pages[i][j]) results <- result } }(i) } go func() { wg.Wait() close(results) }() for result := range results { fmt.Println(result) } }
Ich möchte verstehen, warum es funktioniert:
go func() { wg.Wait() close(results) }()
Mein erster Versuch war erfolglos – ich dachte, ich könnte das Ergebnis beim wg.Wait()
之后遍历通道,并且我会在结果写入 results
Channelieren ablesen.
func main() { // pretend paginated results from initial API request page1 := []int{1, 2, 3} page2 := []int{4, 5, 6} page3 := []int{7, 8, 9} pages := [][]int{page1, page2, page3} results := make(chan string) var wg sync.WaitGroup for i := range pages { wg.Add(1) go func(i int) { defer wg.Done() for j := range pages[i] { // simulate making additional API request and building the report time.Sleep(500 * time.Millisecond) result := fmt.Sprintf("Finished creating report for %d", pages[i][j]) results <- result } }(i) } // does not work wg.Wait() close(results) for result := range results { fmt.Println(result) } }
Lösung
Beim ersten Versuch:
- Die Haupt-Goroutine veranlasst 3 Goroutinen, Werte in den Ergebniskanal einzugeben.
- Die Haupt-Coroutine wartet auf den Abschluss aller Coroutinen.
- Eine der Goroutinen gibt einen Wert in den Ergebniskanal ein und füllt den Kanal (Kanalgröße beträgt 1 String).
- Jetzt können alle drei Goroutinen keine Werte mehr in den Ergebniskanal einfügen und gehen in den Ruhezustand, bis der Ergebniskanal freigegeben wird.
- Alle Goroutinen befinden sich im Ruhezustand. Du steckst in einer Sackgasse.
Beim zweiten Versuch:
- Die Haupt-Goroutine enthält 4 Goroutinen.
- 3 Goroutinen zum Einfügen von Werten in Ergebniskanäle.
- Die andere Goroutine (ich nenne sie die vierte) wartet darauf, dass diese 3 Goroutinen fertig sind.
- Gleichzeitig wartet die Haupt-Coroutine auf den Wert im Ergebniskanal (for-Schleife)
- Wenn in diesem Fall eine der Goroutinen einen Wert in den Ergebniskanal einfügt, blockiert sie die verbleibenden drei Goroutinen; die Haupt-Goroutine entnimmt den Wert aus dem Ergebniskanal und gibt so die Blockierung der anderen Goroutinen frei.
- Also setzen alle 3 Goroutinen ihre jeweiligen Werte und enden
- Dann schließt die vierte Goroutine den Kanal
- Die Haupt-Goroutine beendet ihre for-Schleife.
Das obige ist der detaillierte Inhalt vonSchreiben Sie Chan in die sync.WaitGroup-Goroutine. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



In Go besteht eine Eltern-Kind-Beziehung zwischen Funktionen und Goroutinen. Die übergeordnete Goroutine erstellt die untergeordnete Goroutine, und die untergeordnete Goroutine kann auf die Variablen der übergeordneten Goroutine zugreifen, jedoch nicht umgekehrt. Erstellen Sie eine untergeordnete Goroutine mit dem Schlüsselwort go, und die untergeordnete Goroutine wird über eine anonyme Funktion oder eine benannte Funktion ausgeführt. Die übergeordnete Goroutine kann über sync.WaitGroup auf den Abschluss der untergeordneten Goroutine warten, um sicherzustellen, dass das Programm nicht beendet wird, bevor alle untergeordneten Goroutinen abgeschlossen sind.

Funktionen werden zur sequentiellen Ausführung von Aufgaben verwendet und sind einfach und benutzerfreundlich, weisen jedoch Probleme mit Blockierungen und Ressourcenbeschränkungen auf. Goroutine ist ein leichter Thread, der Aufgaben gleichzeitig ausführt. Er verfügt über hohe Parallelität, Skalierbarkeit und Ereignisverarbeitungsfunktionen, ist jedoch komplex in der Verwendung, teuer und schwierig zu debuggen. Im tatsächlichen Kampf weist Goroutine bei der Ausführung gleichzeitiger Aufgaben normalerweise eine bessere Leistung als Funktionen auf.

In einer Multithread-Umgebung hängt das Verhalten von PHP-Funktionen von ihrem Typ ab: Normale Funktionen: Thread-sicher, können gleichzeitig ausgeführt werden. Funktionen, die globale Variablen ändern: unsicher, müssen einen Synchronisationsmechanismus verwenden. Dateioperationsfunktion: unsicher, zur Koordinierung des Zugriffs muss ein Synchronisierungsmechanismus verwendet werden. Datenbankbetriebsfunktion: Unsicher, Datenbanksystemmechanismus muss verwendet werden, um Konflikte zu verhindern.

Zu den Methoden für die Kommunikation zwischen Threads in C++ gehören: gemeinsam genutzter Speicher, Synchronisationsmechanismen (Mutex-Sperren, Bedingungsvariablen), Pipes und Nachrichtenwarteschlangen. Verwenden Sie beispielsweise eine Mutex-Sperre, um einen gemeinsam genutzten Zähler zu schützen: Deklarieren Sie eine Mutex-Sperre (m) und eine gemeinsam genutzte Variable (Zähler). Stellen Sie sicher, dass jeweils nur ein Thread den Zähler aktualisiert um Rennbedingungen zu verhindern.

Das C++-Parallelitäts-Framework bietet die folgenden Optionen: leichte Threads (std::thread); Thread-sichere Boost-Parallelitätscontainer und -Algorithmen; leistungsstarke ThreadBuildingBlocks (TBB)-Operationsbibliothek (cpp-Concur).

Funktionssperren und Synchronisationsmechanismen in der gleichzeitigen C++-Programmierung werden verwendet, um den gleichzeitigen Zugriff auf Daten in einer Multithread-Umgebung zu verwalten und Datenkonkurrenz zu verhindern. Zu den Hauptmechanismen gehören: Mutex (Mutex): ein Synchronisierungsprimitiv auf niedriger Ebene, das sicherstellt, dass jeweils nur ein Thread auf den kritischen Abschnitt zugreift. Bedingungsvariable (ConditionVariable): Ermöglicht Threads, auf die Erfüllung von Bedingungen zu warten, und ermöglicht die Kommunikation zwischen Threads. Atomare Operation: Einzelanweisungsoperation, die eine Single-Thread-Aktualisierung von Variablen oder Daten gewährleistet, um Konflikte zu vermeiden.

Das Schlüsselwort volatile wird zum Ändern von Variablen verwendet, um sicherzustellen, dass alle Threads den neuesten Wert der Variablen sehen können und um sicherzustellen, dass die Änderung der Variablen ein unterbrechungsfreier Vorgang ist. Zu den Hauptanwendungsszenarien gehören gemeinsam genutzte Multithread-Variablen, Speicherbarrieren und gleichzeitige Programmierung. Es ist jedoch zu beachten, dass volatile keine Thread-Sicherheit garantiert und die Leistung beeinträchtigen kann. Es sollte nur verwendet werden, wenn dies unbedingt erforderlich ist.

Zu den Methoden zur Programmleistungsoptimierung gehören: Algorithmusoptimierung: Wählen Sie einen Algorithmus mit geringerer Zeitkomplexität und reduzieren Sie Schleifen und bedingte Anweisungen. Auswahl der Datenstruktur: Wählen Sie geeignete Datenstrukturen basierend auf Datenzugriffsmustern aus, z. B. Nachschlagebäume und Hash-Tabellen. Speicheroptimierung: Vermeiden Sie die Erstellung unnötiger Objekte, geben Sie nicht mehr verwendeten Speicher frei und verwenden Sie die Speicherpooltechnologie. Thread-Optimierung: Identifizieren Sie Aufgaben, die parallelisiert werden können, und optimieren Sie den Thread-Synchronisierungsmechanismus. Datenbankoptimierung: Erstellen Sie Indizes, um den Datenabruf zu beschleunigen, optimieren Sie Abfrageanweisungen und verwenden Sie Cache- oder NoSQL-Datenbanken, um die Leistung zu verbessern.
