How to Gracefully Stop a Go Routine
In Go, goroutines provide lightweight concurrency, but it can be challenging to terminate them gracefully. This question addresses the need to send a signal to a goroutine to stop its execution.
The code provided demonstrates an attempt to halt a goroutine by setting a boolean flag (tooLate) to true. However, this approach is problematic as reading from a channel blocks the goroutine.
Solution 1: Using an Additional Channel
The solution involves using a second channel (tooLate) to communicate the stop signal. This channel remains open even when the goroutine is not actively reading from it.
<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>
In this solution, when the time limit expires, the tooLate channel is closed, which causes the goroutine to exit its blocking select statement and return.
Solution 2: Using sync.Cond
Alternatively, you can use the sync.Cond type to implement a more sophisticated signaling mechanism. Here is an example:
<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>
With this approach, the goroutine waits on the cond.Wait() method until it receives a signal from cond.Signal().
The above is the detailed content of How to Gracefully Stop a Go Routine: A Guide to Avoiding Deadlocks and Unresponsive Processes?. For more information, please follow other related articles on the PHP Chinese website!