So stoppen Sie eine Go-Routine ordnungsgemäß
In Go bieten Goroutinen eine leichte Parallelität, es kann jedoch schwierig sein, sie ordnungsgemäß zu beenden. Diese Frage befasst sich mit der Notwendigkeit, ein Signal an eine Goroutine zu senden, um deren Ausführung zu stoppen.
Der bereitgestellte Code zeigt einen Versuch, eine Goroutine anzuhalten, indem ein boolesches Flag (tooLate) auf „true“ gesetzt wird. Dieser Ansatz ist jedoch problematisch, da das Lesen aus einem Kanal die Goroutine blockiert.
Lösung 1: Verwendung eines zusätzlichen Kanals
Die Lösung beinhaltet die Verwendung eines zweiten Kanals (tooLate) um das Stoppsignal zu übermitteln. Dieser Kanal bleibt auch dann geöffnet, wenn die Goroutine nicht aktiv daraus liest.
<code class="go">func main() { tooLate := make(chan struct{}) // Unbuffered channel for stop signal proCh := make(chan string) go func() { for { fmt.Println("working") time.Sleep(1 * time.Second) select { case <-tooLate: fmt.Println("stopped") return case proCh <- "processed": // Non-blocking send default: // Allows the goroutine to continue without blocking } fmt.Println("done here") } }() select { case proc := <-proCh: fmt.Println(proc) case <-time.After(1 * time.Second): fmt.Println("too late") close(tooLate) // Signal to goroutine to stop } time.Sleep(4 * time.Second) fmt.Println("finish\n") }</code>
Bei dieser Lösung wird der tooLate-Kanal nach Ablauf des Zeitlimits geschlossen, was dazu führt, dass die Goroutine ihre blockierende Select-Anweisung verlässt und zurück.
Lösung 2: Verwenden von sync.Cond
Alternativ können Sie den Typ sync.Cond verwenden, um einen ausgefeilteren Signalmechanismus zu implementieren. Hier ist ein Beispiel:
<code class="go">func main() { var stopped bool cond := sync.NewCond(new(sync.Mutex)) go func() { for { cond.L.Lock() defer cond.L.Unlock() if stopped { fmt.Println("stopped") return } fmt.Println("working") cond.Wait() // Wait for the signal to stop } }() time.Sleep(1 * time.Second) cond.Signal() // Send the stop signal time.Sleep(4 * time.Second) fmt.Println("finish\n") }</code>
Bei diesem Ansatz wartet die Goroutine auf die cond.Wait()-Methode, bis sie ein Signal von cond.Signal() empfängt.
Das obige ist der detaillierte Inhalt vonWie kann man eine Go-Routine elegant stoppen: Ein Leitfaden zur Vermeidung von Deadlocks und nicht reagierenden Prozessen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!